centaurus-cli 3.0.0 → 3.1.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 (552) hide show
  1. package/dist/ai/types.js +0 -1
  2. package/dist/ai/types.js.map +1 -1
  3. package/dist/cli-adapter.js +5047 -5037
  4. package/dist/cli-adapter.js.map +1 -1
  5. package/dist/commands/CommandParser.js +372 -315
  6. package/dist/commands/CommandParser.js.map +1 -1
  7. package/dist/config/build-config.js +11 -42
  8. package/dist/config/build-config.js.map +1 -1
  9. package/dist/config/defaultConfig.js +94 -82
  10. package/dist/config/defaultConfig.js.map +1 -1
  11. package/dist/config/manager.js +144 -160
  12. package/dist/config/manager.js.map +1 -1
  13. package/dist/config/mcp-config-manager.js +411 -364
  14. package/dist/config/mcp-config-manager.js.map +1 -1
  15. package/dist/config/models.js +118 -185
  16. package/dist/config/models.js.map +1 -1
  17. package/dist/config/slash-commands.js +186 -184
  18. package/dist/config/slash-commands.js.map +1 -1
  19. package/dist/config/types.js +33 -26
  20. package/dist/config/types.js.map +1 -1
  21. package/dist/context/command-detector.js +63 -67
  22. package/dist/context/command-detector.js.map +1 -1
  23. package/dist/context/context-manager.js +533 -518
  24. package/dist/context/context-manager.js.map +1 -1
  25. package/dist/context/handlers/docker-handler.js +518 -576
  26. package/dist/context/handlers/docker-handler.js.map +1 -1
  27. package/dist/context/handlers/ssh-handler.js +1050 -1109
  28. package/dist/context/handlers/ssh-handler.js.map +1 -1
  29. package/dist/context/handlers/wsl-handler.js +558 -630
  30. package/dist/context/handlers/wsl-handler.js.map +1 -1
  31. package/dist/context/index.js +42 -6
  32. package/dist/context/index.js.map +1 -1
  33. package/dist/context/subshell-handler.js +0 -4
  34. package/dist/context/subshell-handler.js.map +1 -1
  35. package/dist/context/types.js +20 -31
  36. package/dist/context/types.js.map +1 -1
  37. package/dist/hooks/useConnectivity.js +13 -10
  38. package/dist/hooks/useConnectivity.js.map +1 -1
  39. package/dist/hooks/useTerminalDimensions.js +67 -79
  40. package/dist/hooks/useTerminalDimensions.js.map +1 -1
  41. package/dist/index.js +228 -251
  42. package/dist/index.js.map +1 -1
  43. package/dist/mcp/mcp-command-handler.js +297 -260
  44. package/dist/mcp/mcp-command-handler.js.map +1 -1
  45. package/dist/mcp/mcp-server-manager.js +139 -155
  46. package/dist/mcp/mcp-server-manager.js.map +1 -1
  47. package/dist/mcp/mcp-tool-wrapper.js +74 -94
  48. package/dist/mcp/mcp-tool-wrapper.js.map +1 -1
  49. package/dist/services/ai-autocomplete-agent.js +169 -181
  50. package/dist/services/ai-autocomplete-agent.js.map +1 -1
  51. package/dist/services/ai-context-injector.js +180 -93
  52. package/dist/services/ai-context-injector.js.map +1 -1
  53. package/dist/services/ai-service-client.js +513 -456
  54. package/dist/services/ai-service-client.js.map +1 -1
  55. package/dist/services/api-client.js +443 -441
  56. package/dist/services/api-client.js.map +1 -1
  57. package/dist/services/auth-handler.js +162 -198
  58. package/dist/services/auth-handler.js.map +1 -1
  59. package/dist/services/background-task-manager.js +258 -282
  60. package/dist/services/background-task-manager.js.map +1 -1
  61. package/dist/services/checkpoint-manager.js +1513 -973
  62. package/dist/services/checkpoint-manager.js.map +1 -1
  63. package/dist/services/clipboard-service.js +151 -200
  64. package/dist/services/clipboard-service.js.map +1 -1
  65. package/dist/services/connectivity-manager.js +63 -65
  66. package/dist/services/connectivity-manager.js.map +1 -1
  67. package/dist/services/conversation-manager.js +118 -121
  68. package/dist/services/conversation-manager.js.map +1 -1
  69. package/dist/services/environment-context-injector.js +160 -187
  70. package/dist/services/environment-context-injector.js.map +1 -1
  71. package/dist/services/fast-context-agent.js +203 -243
  72. package/dist/services/fast-context-agent.js.map +1 -1
  73. package/dist/services/input-detection-agent.js +190 -202
  74. package/dist/services/input-detection-agent.js.map +1 -1
  75. package/dist/services/input-requirement-detector.js +155 -189
  76. package/dist/services/input-requirement-detector.js.map +1 -1
  77. package/dist/services/local-chat-storage.js +342 -365
  78. package/dist/services/local-chat-storage.js.map +1 -1
  79. package/dist/services/monitored-shell-manager.js +225 -233
  80. package/dist/services/monitored-shell-manager.js.map +1 -1
  81. package/dist/services/ollama-service.js +293 -310
  82. package/dist/services/ollama-service.js.map +1 -1
  83. package/dist/services/rules-storage.js +142 -0
  84. package/dist/services/rules-storage.js.map +1 -0
  85. package/dist/services/session-quota-manager.js +219 -235
  86. package/dist/services/session-quota-manager.js.map +1 -1
  87. package/dist/services/shell-input-agent.js +299 -334
  88. package/dist/services/shell-input-agent.js.map +1 -1
  89. package/dist/services/sub-agent-manager.js +459 -501
  90. package/dist/services/sub-agent-manager.js.map +1 -1
  91. package/dist/services/warpify-detector.js +133 -183
  92. package/dist/services/warpify-detector.js.map +1 -1
  93. package/dist/services/workflow-storage.js +202 -217
  94. package/dist/services/workflow-storage.js.map +1 -1
  95. package/dist/test-ssh-handler.js +148 -193
  96. package/dist/test-ssh-handler.js.map +1 -1
  97. package/dist/tools/add-mcp.js +161 -0
  98. package/dist/tools/add-mcp.js.map +1 -0
  99. package/dist/tools/background-command.js +240 -273
  100. package/dist/tools/background-command.js.map +1 -1
  101. package/dist/tools/command.js +447 -440
  102. package/dist/tools/command.js.map +1 -1
  103. package/dist/tools/create-image.js +172 -202
  104. package/dist/tools/create-image.js.map +1 -1
  105. package/dist/tools/enter-remote-session.js +169 -215
  106. package/dist/tools/enter-remote-session.js.map +1 -1
  107. package/dist/tools/fast-context.js +60 -67
  108. package/dist/tools/fast-context.js.map +1 -1
  109. package/dist/tools/file-ops.js +605 -537
  110. package/dist/tools/file-ops.js.map +1 -1
  111. package/dist/tools/find-files.js +262 -303
  112. package/dist/tools/find-files.js.map +1 -1
  113. package/dist/tools/get-diff.js +423 -400
  114. package/dist/tools/get-diff.js.map +1 -1
  115. package/dist/tools/grep-search.js +966 -948
  116. package/dist/tools/grep-search.js.map +1 -1
  117. package/dist/tools/inspect-symbol.js +308 -323
  118. package/dist/tools/inspect-symbol.js.map +1 -1
  119. package/dist/tools/plan-mode.js +459 -503
  120. package/dist/tools/plan-mode.js.map +1 -1
  121. package/dist/tools/read-binary-file.js +160 -190
  122. package/dist/tools/read-binary-file.js.map +1 -1
  123. package/dist/tools/registry.js +100 -84
  124. package/dist/tools/registry.js.map +1 -1
  125. package/dist/tools/reproduce_issue.js +170 -151
  126. package/dist/tools/reproduce_issue.js.map +1 -1
  127. package/dist/tools/sub-agent.js +223 -228
  128. package/dist/tools/sub-agent.js.map +1 -1
  129. package/dist/tools/task-complete.js +28 -27
  130. package/dist/tools/task-complete.js.map +1 -1
  131. package/dist/tools/types.js +0 -1
  132. package/dist/tools/types.js.map +1 -1
  133. package/dist/tools/validation.js +96 -118
  134. package/dist/tools/validation.js.map +1 -1
  135. package/dist/tools/web-search.js +194 -194
  136. package/dist/tools/web-search.js.map +1 -1
  137. package/dist/tools/workflow-tool.js +77 -82
  138. package/dist/tools/workflow-tool.js.map +1 -1
  139. package/dist/types/index.js +0 -1
  140. package/dist/types/index.js.map +1 -1
  141. package/dist/types/rule.js +1 -0
  142. package/dist/types/rule.js.map +1 -0
  143. package/dist/types/workflow.js +0 -7
  144. package/dist/types/workflow.js.map +1 -1
  145. package/dist/ui/components/AgentTimer.js +24 -25
  146. package/dist/ui/components/AgentTimer.js.map +1 -1
  147. package/dist/ui/components/App.js +3266 -3249
  148. package/dist/ui/components/App.js.map +1 -1
  149. package/dist/ui/components/AuthScreen.js +22 -34
  150. package/dist/ui/components/AuthScreen.js.map +1 -1
  151. package/dist/ui/components/AuthWelcomeScreen.js +30 -24
  152. package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
  153. package/dist/ui/components/Breadcrumbs.js +53 -82
  154. package/dist/ui/components/Breadcrumbs.js.map +1 -1
  155. package/dist/ui/components/CircularSelectInput.js +59 -67
  156. package/dist/ui/components/CircularSelectInput.js.map +1 -1
  157. package/dist/ui/components/ClipboardFileAutocomplete.js +78 -39
  158. package/dist/ui/components/ClipboardFileAutocomplete.js.map +1 -1
  159. package/dist/ui/components/CodeBlock.js +24 -42
  160. package/dist/ui/components/CodeBlock.js.map +1 -1
  161. package/dist/ui/components/ConfigViewer.js +18 -25
  162. package/dist/ui/components/ConfigViewer.js.map +1 -1
  163. package/dist/ui/components/ConfirmPrompt.js +49 -71
  164. package/dist/ui/components/ConfirmPrompt.js.map +1 -1
  165. package/dist/ui/components/ConnectionStatusMessage.js +32 -83
  166. package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
  167. package/dist/ui/components/ContextWindowIndicator.js +34 -49
  168. package/dist/ui/components/ContextWindowIndicator.js.map +1 -1
  169. package/dist/ui/components/DetailedPlanReviewScreen.js +104 -106
  170. package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
  171. package/dist/ui/components/DiffViewer.js +68 -121
  172. package/dist/ui/components/DiffViewer.js.map +1 -1
  173. package/dist/ui/components/ErrorBoundary.js +40 -48
  174. package/dist/ui/components/ErrorBoundary.js.map +1 -1
  175. package/dist/ui/components/FileCreationPreview.js +29 -60
  176. package/dist/ui/components/FileCreationPreview.js.map +1 -1
  177. package/dist/ui/components/FileOperation.js +34 -29
  178. package/dist/ui/components/FileOperation.js.map +1 -1
  179. package/dist/ui/components/FileTagAutocomplete.js +55 -25
  180. package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
  181. package/dist/ui/components/FontRecommendation.js.map +1 -1
  182. package/dist/ui/components/GitDiffBreadcrumb.js +29 -0
  183. package/dist/ui/components/GitDiffBreadcrumb.js.map +1 -0
  184. package/dist/ui/components/InputBox.js +1620 -2150
  185. package/dist/ui/components/InputBox.js.map +1 -1
  186. package/dist/ui/components/InteractiveShell.js +234 -352
  187. package/dist/ui/components/InteractiveShell.js.map +1 -1
  188. package/dist/ui/components/KeyboardHelp.js +34 -35
  189. package/dist/ui/components/KeyboardHelp.js.map +1 -1
  190. package/dist/ui/components/LoadingIndicator.js +22 -25
  191. package/dist/ui/components/LoadingIndicator.js.map +1 -1
  192. package/dist/ui/components/MCPAddScreen.js +40 -51
  193. package/dist/ui/components/MCPAddScreen.js.map +1 -1
  194. package/dist/ui/components/MCPListScreen.js +40 -48
  195. package/dist/ui/components/MCPListScreen.js.map +1 -1
  196. package/dist/ui/components/MCPServerListScreen.js +49 -56
  197. package/dist/ui/components/MCPServerListScreen.js.map +1 -1
  198. package/dist/ui/components/MarkdownRenderer.js +69 -96
  199. package/dist/ui/components/MarkdownRenderer.js.map +1 -1
  200. package/dist/ui/components/MessageBox.js +66 -48
  201. package/dist/ui/components/MessageBox.js.map +1 -1
  202. package/dist/ui/components/MessageDisplay.js +150 -142
  203. package/dist/ui/components/MessageDisplay.js.map +1 -1
  204. package/dist/ui/components/MonitorModeAIPanel.js +46 -65
  205. package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
  206. package/dist/ui/components/MultiLineInput.js +243 -277
  207. package/dist/ui/components/MultiLineInput.js.map +1 -1
  208. package/dist/ui/components/PasswordPrompt.js +37 -18
  209. package/dist/ui/components/PasswordPrompt.js.map +1 -1
  210. package/dist/ui/components/PlanAcceptedMessage.js +27 -38
  211. package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
  212. package/dist/ui/components/PlanReviewScreen.js +46 -50
  213. package/dist/ui/components/PlanReviewScreen.js.map +1 -1
  214. package/dist/ui/components/RulesEditorScreen.js +81 -0
  215. package/dist/ui/components/RulesEditorScreen.js.map +1 -0
  216. package/dist/ui/components/SelectPrompt.js +19 -8
  217. package/dist/ui/components/SelectPrompt.js.map +1 -1
  218. package/dist/ui/components/ShimmerText.js +44 -0
  219. package/dist/ui/components/ShimmerText.js.map +1 -0
  220. package/dist/ui/components/SlashCommandAutocomplete.js +49 -22
  221. package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
  222. package/dist/ui/components/StatusBar.js +56 -87
  223. package/dist/ui/components/StatusBar.js.map +1 -1
  224. package/dist/ui/components/StreamingMessageDisplay.js +116 -99
  225. package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
  226. package/dist/ui/components/TaskCompletedMessage.js +28 -23
  227. package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
  228. package/dist/ui/components/TaskProgressIndicator.js +44 -70
  229. package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
  230. package/dist/ui/components/ThinkingDisplay.js +44 -41
  231. package/dist/ui/components/ThinkingDisplay.js.map +1 -1
  232. package/dist/ui/components/ToolExecutionMessage.js +772 -1326
  233. package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
  234. package/dist/ui/components/ToolExecutionStatus.js +53 -84
  235. package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
  236. package/dist/ui/components/ToolResult.js +22 -15
  237. package/dist/ui/components/ToolResult.js.map +1 -1
  238. package/dist/ui/components/VersionUpdatePrompt.js +88 -120
  239. package/dist/ui/components/VersionUpdatePrompt.js.map +1 -1
  240. package/dist/ui/components/WelcomeBanner.js +176 -26
  241. package/dist/ui/components/WelcomeBanner.js.map +1 -1
  242. package/dist/ui/components/WorkflowCreatorScreen.js +94 -161
  243. package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
  244. package/dist/utils/ansi-encoder.js +30 -61
  245. package/dist/utils/ansi-encoder.js.map +1 -1
  246. package/dist/utils/chat-formatter.js +327 -305
  247. package/dist/utils/chat-formatter.js.map +1 -1
  248. package/dist/utils/command-history.js +152 -174
  249. package/dist/utils/command-history.js.map +1 -1
  250. package/dist/utils/context-sanitizer.js +49 -112
  251. package/dist/utils/context-sanitizer.js.map +1 -1
  252. package/dist/utils/conversation-logger.js +292 -324
  253. package/dist/utils/conversation-logger.js.map +1 -1
  254. package/dist/utils/custom-commands-manager.js +126 -131
  255. package/dist/utils/custom-commands-manager.js.map +1 -1
  256. package/dist/utils/editor-utils.js +732 -837
  257. package/dist/utils/editor-utils.js.map +1 -1
  258. package/dist/utils/file.js +174 -213
  259. package/dist/utils/file.js.map +1 -1
  260. package/dist/utils/git-stats.js +169 -0
  261. package/dist/utils/git-stats.js.map +1 -0
  262. package/dist/utils/input-classifier.js +960 -482
  263. package/dist/utils/input-classifier.js.map +1 -1
  264. package/dist/utils/logger.js +48 -73
  265. package/dist/utils/logger.js.map +1 -1
  266. package/dist/utils/markdown-parser.js +277 -310
  267. package/dist/utils/markdown-parser.js.map +1 -1
  268. package/dist/utils/rule-reference-resolver.js +54 -0
  269. package/dist/utils/rule-reference-resolver.js.map +1 -0
  270. package/dist/utils/shell.js +144 -156
  271. package/dist/utils/shell.js.map +1 -1
  272. package/dist/utils/state.js +23 -22
  273. package/dist/utils/state.js.map +1 -1
  274. package/dist/utils/syntax-checker.js +279 -327
  275. package/dist/utils/syntax-checker.js.map +1 -1
  276. package/dist/utils/terminal-output.js +199 -302
  277. package/dist/utils/terminal-output.js.map +1 -1
  278. package/dist/utils/text-clipboard.js +47 -70
  279. package/dist/utils/text-clipboard.js.map +1 -1
  280. package/dist/utils/unicode-sanitizer.js +134 -197
  281. package/dist/utils/unicode-sanitizer.js.map +1 -1
  282. package/dist/utils/version-checker.js +46 -56
  283. package/dist/utils/version-checker.js.map +1 -1
  284. package/package.json +6 -4
  285. package/dist/ai/types.d.ts +0 -20
  286. package/dist/ai/types.d.ts.map +0 -1
  287. package/dist/cli-adapter.d.ts +0 -511
  288. package/dist/cli-adapter.d.ts.map +0 -1
  289. package/dist/commands/CommandParser.d.ts +0 -27
  290. package/dist/commands/CommandParser.d.ts.map +0 -1
  291. package/dist/config/build-config.d.ts +0 -42
  292. package/dist/config/build-config.d.ts.map +0 -1
  293. package/dist/config/defaultConfig.d.ts +0 -79
  294. package/dist/config/defaultConfig.d.ts.map +0 -1
  295. package/dist/config/manager.d.ts +0 -62
  296. package/dist/config/manager.d.ts.map +0 -1
  297. package/dist/config/mcp-config-manager.d.ts +0 -79
  298. package/dist/config/mcp-config-manager.d.ts.map +0 -1
  299. package/dist/config/models.d.ts +0 -83
  300. package/dist/config/models.d.ts.map +0 -1
  301. package/dist/config/slash-commands.d.ts +0 -23
  302. package/dist/config/slash-commands.d.ts.map +0 -1
  303. package/dist/config/types.d.ts +0 -35
  304. package/dist/config/types.d.ts.map +0 -1
  305. package/dist/context/command-detector.d.ts +0 -50
  306. package/dist/context/command-detector.d.ts.map +0 -1
  307. package/dist/context/context-manager.d.ts +0 -157
  308. package/dist/context/context-manager.d.ts.map +0 -1
  309. package/dist/context/handlers/docker-handler.d.ts +0 -130
  310. package/dist/context/handlers/docker-handler.d.ts.map +0 -1
  311. package/dist/context/handlers/ssh-handler.d.ts +0 -201
  312. package/dist/context/handlers/ssh-handler.d.ts.map +0 -1
  313. package/dist/context/handlers/wsl-handler.d.ts +0 -146
  314. package/dist/context/handlers/wsl-handler.d.ts.map +0 -1
  315. package/dist/context/index.d.ts +0 -8
  316. package/dist/context/index.d.ts.map +0 -1
  317. package/dist/context/subshell-handler.d.ts +0 -165
  318. package/dist/context/subshell-handler.d.ts.map +0 -1
  319. package/dist/context/types.d.ts +0 -70
  320. package/dist/context/types.d.ts.map +0 -1
  321. package/dist/hooks/useConnectivity.d.ts +0 -2
  322. package/dist/hooks/useConnectivity.d.ts.map +0 -1
  323. package/dist/hooks/useTerminalDimensions.d.ts +0 -41
  324. package/dist/hooks/useTerminalDimensions.d.ts.map +0 -1
  325. package/dist/index.d.ts +0 -9
  326. package/dist/index.d.ts.map +0 -1
  327. package/dist/mcp/mcp-command-handler.d.ts +0 -47
  328. package/dist/mcp/mcp-command-handler.d.ts.map +0 -1
  329. package/dist/mcp/mcp-server-manager.d.ts +0 -30
  330. package/dist/mcp/mcp-server-manager.d.ts.map +0 -1
  331. package/dist/mcp/mcp-tool-wrapper.d.ts +0 -12
  332. package/dist/mcp/mcp-tool-wrapper.d.ts.map +0 -1
  333. package/dist/services/ai-autocomplete-agent.d.ts +0 -39
  334. package/dist/services/ai-autocomplete-agent.d.ts.map +0 -1
  335. package/dist/services/ai-context-injector.d.ts +0 -41
  336. package/dist/services/ai-context-injector.d.ts.map +0 -1
  337. package/dist/services/ai-service-client.d.ts +0 -128
  338. package/dist/services/ai-service-client.d.ts.map +0 -1
  339. package/dist/services/api-client.d.ts +0 -353
  340. package/dist/services/api-client.d.ts.map +0 -1
  341. package/dist/services/auth-handler.d.ts +0 -30
  342. package/dist/services/auth-handler.d.ts.map +0 -1
  343. package/dist/services/background-task-manager.d.ts +0 -114
  344. package/dist/services/background-task-manager.d.ts.map +0 -1
  345. package/dist/services/checkpoint-manager.d.ts +0 -167
  346. package/dist/services/checkpoint-manager.d.ts.map +0 -1
  347. package/dist/services/clipboard-service.d.ts +0 -37
  348. package/dist/services/clipboard-service.d.ts.map +0 -1
  349. package/dist/services/connectivity-manager.d.ts +0 -18
  350. package/dist/services/connectivity-manager.d.ts.map +0 -1
  351. package/dist/services/conversation-manager.d.ts +0 -73
  352. package/dist/services/conversation-manager.d.ts.map +0 -1
  353. package/dist/services/environment-context-injector.d.ts +0 -69
  354. package/dist/services/environment-context-injector.d.ts.map +0 -1
  355. package/dist/services/fast-context-agent.d.ts +0 -12
  356. package/dist/services/fast-context-agent.d.ts.map +0 -1
  357. package/dist/services/input-detection-agent.d.ts +0 -40
  358. package/dist/services/input-detection-agent.d.ts.map +0 -1
  359. package/dist/services/input-requirement-detector.d.ts +0 -28
  360. package/dist/services/input-requirement-detector.d.ts.map +0 -1
  361. package/dist/services/local-chat-storage.d.ts +0 -182
  362. package/dist/services/local-chat-storage.d.ts.map +0 -1
  363. package/dist/services/monitored-shell-manager.d.ts +0 -120
  364. package/dist/services/monitored-shell-manager.d.ts.map +0 -1
  365. package/dist/services/ollama-service.d.ts +0 -197
  366. package/dist/services/ollama-service.d.ts.map +0 -1
  367. package/dist/services/session-quota-manager.d.ts +0 -101
  368. package/dist/services/session-quota-manager.d.ts.map +0 -1
  369. package/dist/services/shell-input-agent.d.ts +0 -89
  370. package/dist/services/shell-input-agent.d.ts.map +0 -1
  371. package/dist/services/sub-agent-manager.d.ts +0 -140
  372. package/dist/services/sub-agent-manager.d.ts.map +0 -1
  373. package/dist/services/warpify-detector.d.ts +0 -43
  374. package/dist/services/warpify-detector.d.ts.map +0 -1
  375. package/dist/services/workflow-storage.d.ts +0 -72
  376. package/dist/services/workflow-storage.d.ts.map +0 -1
  377. package/dist/test-ssh-handler.d.ts +0 -8
  378. package/dist/test-ssh-handler.d.ts.map +0 -1
  379. package/dist/tools/background-command.d.ts +0 -11
  380. package/dist/tools/background-command.d.ts.map +0 -1
  381. package/dist/tools/command.d.ts +0 -3
  382. package/dist/tools/command.d.ts.map +0 -1
  383. package/dist/tools/create-image.d.ts +0 -10
  384. package/dist/tools/create-image.d.ts.map +0 -1
  385. package/dist/tools/enter-remote-session.d.ts +0 -48
  386. package/dist/tools/enter-remote-session.d.ts.map +0 -1
  387. package/dist/tools/fast-context.d.ts +0 -3
  388. package/dist/tools/fast-context.d.ts.map +0 -1
  389. package/dist/tools/file-ops.d.ts +0 -7
  390. package/dist/tools/file-ops.d.ts.map +0 -1
  391. package/dist/tools/find-files.d.ts +0 -49
  392. package/dist/tools/find-files.d.ts.map +0 -1
  393. package/dist/tools/get-diff.d.ts +0 -14
  394. package/dist/tools/get-diff.d.ts.map +0 -1
  395. package/dist/tools/grep-search.d.ts +0 -155
  396. package/dist/tools/grep-search.d.ts.map +0 -1
  397. package/dist/tools/inspect-symbol.d.ts +0 -32
  398. package/dist/tools/inspect-symbol.d.ts.map +0 -1
  399. package/dist/tools/plan-mode.d.ts +0 -140
  400. package/dist/tools/plan-mode.d.ts.map +0 -1
  401. package/dist/tools/read-binary-file.d.ts +0 -10
  402. package/dist/tools/read-binary-file.d.ts.map +0 -1
  403. package/dist/tools/registry.d.ts +0 -31
  404. package/dist/tools/registry.d.ts.map +0 -1
  405. package/dist/tools/reproduce_issue.d.ts +0 -2
  406. package/dist/tools/reproduce_issue.d.ts.map +0 -1
  407. package/dist/tools/sub-agent.d.ts +0 -9
  408. package/dist/tools/sub-agent.d.ts.map +0 -1
  409. package/dist/tools/task-complete.d.ts +0 -3
  410. package/dist/tools/task-complete.d.ts.map +0 -1
  411. package/dist/tools/types.d.ts +0 -40
  412. package/dist/tools/types.d.ts.map +0 -1
  413. package/dist/tools/validation.d.ts +0 -47
  414. package/dist/tools/validation.d.ts.map +0 -1
  415. package/dist/tools/web-search.d.ts +0 -24
  416. package/dist/tools/web-search.d.ts.map +0 -1
  417. package/dist/tools/workflow-tool.d.ts +0 -11
  418. package/dist/tools/workflow-tool.d.ts.map +0 -1
  419. package/dist/types/index.d.ts +0 -123
  420. package/dist/types/index.d.ts.map +0 -1
  421. package/dist/types/workflow.d.ts +0 -110
  422. package/dist/types/workflow.d.ts.map +0 -1
  423. package/dist/ui/components/AgentTimer.d.ts +0 -7
  424. package/dist/ui/components/AgentTimer.d.ts.map +0 -1
  425. package/dist/ui/components/App.d.ts +0 -197
  426. package/dist/ui/components/App.d.ts.map +0 -1
  427. package/dist/ui/components/AuthScreen.d.ts +0 -8
  428. package/dist/ui/components/AuthScreen.d.ts.map +0 -1
  429. package/dist/ui/components/AuthWelcomeScreen.d.ts +0 -8
  430. package/dist/ui/components/AuthWelcomeScreen.d.ts.map +0 -1
  431. package/dist/ui/components/Breadcrumbs.d.ts +0 -13
  432. package/dist/ui/components/Breadcrumbs.d.ts.map +0 -1
  433. package/dist/ui/components/CircularSelectInput.d.ts +0 -24
  434. package/dist/ui/components/CircularSelectInput.d.ts.map +0 -1
  435. package/dist/ui/components/ClipboardFileAutocomplete.d.ts +0 -10
  436. package/dist/ui/components/ClipboardFileAutocomplete.d.ts.map +0 -1
  437. package/dist/ui/components/CodeBlock.d.ts +0 -9
  438. package/dist/ui/components/CodeBlock.d.ts.map +0 -1
  439. package/dist/ui/components/ConfigViewer.d.ts +0 -11
  440. package/dist/ui/components/ConfigViewer.d.ts.map +0 -1
  441. package/dist/ui/components/ConfirmPrompt.d.ts +0 -13
  442. package/dist/ui/components/ConfirmPrompt.d.ts.map +0 -1
  443. package/dist/ui/components/ConnectionStatusMessage.d.ts +0 -17
  444. package/dist/ui/components/ConnectionStatusMessage.d.ts.map +0 -1
  445. package/dist/ui/components/ContextWindowIndicator.d.ts +0 -8
  446. package/dist/ui/components/ContextWindowIndicator.d.ts.map +0 -1
  447. package/dist/ui/components/DetailedPlanReviewScreen.d.ts +0 -17
  448. package/dist/ui/components/DetailedPlanReviewScreen.d.ts.map +0 -1
  449. package/dist/ui/components/DiffViewer.d.ts +0 -9
  450. package/dist/ui/components/DiffViewer.d.ts.map +0 -1
  451. package/dist/ui/components/ErrorBoundary.d.ts +0 -17
  452. package/dist/ui/components/ErrorBoundary.d.ts.map +0 -1
  453. package/dist/ui/components/FileCreationPreview.d.ts +0 -8
  454. package/dist/ui/components/FileCreationPreview.d.ts.map +0 -1
  455. package/dist/ui/components/FileOperation.d.ts +0 -10
  456. package/dist/ui/components/FileOperation.d.ts.map +0 -1
  457. package/dist/ui/components/FileTagAutocomplete.d.ts +0 -11
  458. package/dist/ui/components/FileTagAutocomplete.d.ts.map +0 -1
  459. package/dist/ui/components/FontRecommendation.d.ts +0 -1
  460. package/dist/ui/components/FontRecommendation.d.ts.map +0 -1
  461. package/dist/ui/components/InputBox.d.ts +0 -42
  462. package/dist/ui/components/InputBox.d.ts.map +0 -1
  463. package/dist/ui/components/InteractiveShell.d.ts +0 -30
  464. package/dist/ui/components/InteractiveShell.d.ts.map +0 -1
  465. package/dist/ui/components/KeyboardHelp.d.ts +0 -7
  466. package/dist/ui/components/KeyboardHelp.d.ts.map +0 -1
  467. package/dist/ui/components/LoadingIndicator.d.ts +0 -3
  468. package/dist/ui/components/LoadingIndicator.d.ts.map +0 -1
  469. package/dist/ui/components/MCPAddScreen.d.ts +0 -13
  470. package/dist/ui/components/MCPAddScreen.d.ts.map +0 -1
  471. package/dist/ui/components/MCPListScreen.d.ts +0 -17
  472. package/dist/ui/components/MCPListScreen.d.ts.map +0 -1
  473. package/dist/ui/components/MCPServerListScreen.d.ts +0 -16
  474. package/dist/ui/components/MCPServerListScreen.d.ts.map +0 -1
  475. package/dist/ui/components/MarkdownRenderer.d.ts +0 -8
  476. package/dist/ui/components/MarkdownRenderer.d.ts.map +0 -1
  477. package/dist/ui/components/MessageBox.d.ts +0 -10
  478. package/dist/ui/components/MessageBox.d.ts.map +0 -1
  479. package/dist/ui/components/MessageDisplay.d.ts +0 -14
  480. package/dist/ui/components/MessageDisplay.d.ts.map +0 -1
  481. package/dist/ui/components/MonitorModeAIPanel.d.ts +0 -23
  482. package/dist/ui/components/MonitorModeAIPanel.d.ts.map +0 -1
  483. package/dist/ui/components/MultiLineInput.d.ts +0 -13
  484. package/dist/ui/components/MultiLineInput.d.ts.map +0 -1
  485. package/dist/ui/components/PasswordPrompt.d.ts +0 -9
  486. package/dist/ui/components/PasswordPrompt.d.ts.map +0 -1
  487. package/dist/ui/components/PlanAcceptedMessage.d.ts +0 -20
  488. package/dist/ui/components/PlanAcceptedMessage.d.ts.map +0 -1
  489. package/dist/ui/components/PlanReviewScreen.d.ts +0 -14
  490. package/dist/ui/components/PlanReviewScreen.d.ts.map +0 -1
  491. package/dist/ui/components/SelectPrompt.d.ts +0 -12
  492. package/dist/ui/components/SelectPrompt.d.ts.map +0 -1
  493. package/dist/ui/components/SlashCommandAutocomplete.d.ts +0 -13
  494. package/dist/ui/components/SlashCommandAutocomplete.d.ts.map +0 -1
  495. package/dist/ui/components/StatusBar.d.ts +0 -14
  496. package/dist/ui/components/StatusBar.d.ts.map +0 -1
  497. package/dist/ui/components/StreamingMessageDisplay.d.ts +0 -15
  498. package/dist/ui/components/StreamingMessageDisplay.d.ts.map +0 -1
  499. package/dist/ui/components/TaskCompletedMessage.d.ts +0 -14
  500. package/dist/ui/components/TaskCompletedMessage.d.ts.map +0 -1
  501. package/dist/ui/components/TaskProgressIndicator.d.ts +0 -18
  502. package/dist/ui/components/TaskProgressIndicator.d.ts.map +0 -1
  503. package/dist/ui/components/ThinkingDisplay.d.ts +0 -15
  504. package/dist/ui/components/ThinkingDisplay.d.ts.map +0 -1
  505. package/dist/ui/components/ToolExecutionMessage.d.ts +0 -8
  506. package/dist/ui/components/ToolExecutionMessage.d.ts.map +0 -1
  507. package/dist/ui/components/ToolExecutionStatus.d.ts +0 -10
  508. package/dist/ui/components/ToolExecutionStatus.d.ts.map +0 -1
  509. package/dist/ui/components/ToolResult.d.ts +0 -10
  510. package/dist/ui/components/ToolResult.d.ts.map +0 -1
  511. package/dist/ui/components/VersionUpdatePrompt.d.ts +0 -9
  512. package/dist/ui/components/VersionUpdatePrompt.d.ts.map +0 -1
  513. package/dist/ui/components/WelcomeBanner.d.ts +0 -3
  514. package/dist/ui/components/WelcomeBanner.d.ts.map +0 -1
  515. package/dist/ui/components/WorkflowCreatorScreen.d.ts +0 -25
  516. package/dist/ui/components/WorkflowCreatorScreen.d.ts.map +0 -1
  517. package/dist/utils/ansi-encoder.d.ts +0 -7
  518. package/dist/utils/ansi-encoder.d.ts.map +0 -1
  519. package/dist/utils/chat-formatter.d.ts +0 -12
  520. package/dist/utils/chat-formatter.d.ts.map +0 -1
  521. package/dist/utils/command-history.d.ts +0 -24
  522. package/dist/utils/command-history.d.ts.map +0 -1
  523. package/dist/utils/context-sanitizer.d.ts +0 -50
  524. package/dist/utils/context-sanitizer.d.ts.map +0 -1
  525. package/dist/utils/conversation-logger.d.ts +0 -142
  526. package/dist/utils/conversation-logger.d.ts.map +0 -1
  527. package/dist/utils/custom-commands-manager.d.ts +0 -59
  528. package/dist/utils/custom-commands-manager.d.ts.map +0 -1
  529. package/dist/utils/editor-utils.d.ts +0 -101
  530. package/dist/utils/editor-utils.d.ts.map +0 -1
  531. package/dist/utils/file.d.ts +0 -61
  532. package/dist/utils/file.d.ts.map +0 -1
  533. package/dist/utils/input-classifier.d.ts +0 -25
  534. package/dist/utils/input-classifier.d.ts.map +0 -1
  535. package/dist/utils/logger.d.ts +0 -17
  536. package/dist/utils/logger.d.ts.map +0 -1
  537. package/dist/utils/markdown-parser.d.ts +0 -60
  538. package/dist/utils/markdown-parser.d.ts.map +0 -1
  539. package/dist/utils/shell.d.ts +0 -47
  540. package/dist/utils/shell.d.ts.map +0 -1
  541. package/dist/utils/state.d.ts +0 -13
  542. package/dist/utils/state.d.ts.map +0 -1
  543. package/dist/utils/syntax-checker.d.ts +0 -24
  544. package/dist/utils/syntax-checker.d.ts.map +0 -1
  545. package/dist/utils/terminal-output.d.ts +0 -25
  546. package/dist/utils/terminal-output.d.ts.map +0 -1
  547. package/dist/utils/text-clipboard.d.ts +0 -12
  548. package/dist/utils/text-clipboard.d.ts.map +0 -1
  549. package/dist/utils/unicode-sanitizer.d.ts +0 -44
  550. package/dist/utils/unicode-sanitizer.d.ts.map +0 -1
  551. package/dist/utils/version-checker.d.ts +0 -14
  552. package/dist/utils/version-checker.d.ts.map +0 -1
@@ -1,895 +1,790 @@
1
- import * as os from 'os';
2
- import { createRequire } from 'module';
3
- import { logError } from './logger.js';
4
- // Use createRequire for ESM compatibility with native modules
5
- const require = createRequire(import.meta.url);
6
- const nodePty = require('@homebridge/node-pty-prebuilt-multiarch');
7
- /**
8
- * List of interactive editor commands that require full terminal control
9
- */
1
+ import * as os from "os";
2
+ import { createRequire } from "module";
3
+ import { logError } from "./logger.js";
4
+ const require2 = createRequire(import.meta.url);
5
+ const nodePty = require2("@homebridge/node-pty-prebuilt-multiarch");
10
6
  const INTERACTIVE_EDITORS = [
11
- 'vim', 'nvim', 'vi', 'nano', 'emacs', 'micro', 'helix', 'hx',
12
- 'pico', 'joe', 'ne', 'mcedit'
7
+ "vim",
8
+ "nvim",
9
+ "vi",
10
+ "nano",
11
+ "emacs",
12
+ "micro",
13
+ "helix",
14
+ "hx",
15
+ "pico",
16
+ "joe",
17
+ "ne",
18
+ "mcedit"
13
19
  ];
14
- /**
15
- * Patterns that indicate an editor will be opened
16
- */
17
20
  const EDITOR_PATTERNS = [
18
- /^git\s+rebase\s+-i/, // git rebase -i (interactive)
19
- /^crontab\s+-e/, // crontab -e (opens editor)
20
- /^visudo/, // visudo (opens editor)
21
- /^vipw/, // vipw (opens editor)
22
- /^sudoedit/, // sudoedit (opens editor)
21
+ /^git\s+rebase\s+-i/,
22
+ // git rebase -i (interactive)
23
+ /^crontab\s+-e/,
24
+ // crontab -e (opens editor)
25
+ /^visudo/,
26
+ // visudo (opens editor)
27
+ /^vipw/,
28
+ // vipw (opens editor)
29
+ /^sudoedit/
30
+ // sudoedit (opens editor)
23
31
  ];
24
- /**
25
- * Check if a command is an interactive editor that needs full terminal control
26
- */
27
- export function isInteractiveEditorCommand(command) {
28
- const trimmed = command.trim();
29
- const parts = trimmed.split(/\s+/);
30
- const baseCommand = parts[0].toLowerCase();
31
- // Direct editor commands
32
- if (INTERACTIVE_EDITORS.includes(baseCommand)) {
33
- return true;
32
+ function isInteractiveEditorCommand(command) {
33
+ const trimmed = command.trim();
34
+ const parts = trimmed.split(/\s+/);
35
+ const baseCommand = parts[0].toLowerCase();
36
+ if (INTERACTIVE_EDITORS.includes(baseCommand)) {
37
+ return true;
38
+ }
39
+ for (const pattern of EDITOR_PATTERNS) {
40
+ if (pattern.test(trimmed)) {
41
+ return true;
34
42
  }
35
- // Check patterns
36
- for (const pattern of EDITOR_PATTERNS) {
37
- if (pattern.test(trimmed)) {
38
- return true;
39
- }
40
- }
41
- // Handle sudo/doas prefix
42
- if (baseCommand === 'sudo' || baseCommand === 'doas') {
43
- const actualCommand = parts.slice(1).join(' ');
44
- return isInteractiveEditorCommand(actualCommand);
45
- }
46
- return false;
43
+ }
44
+ if (baseCommand === "sudo" || baseCommand === "doas") {
45
+ const actualCommand = parts.slice(1).join(" ");
46
+ return isInteractiveEditorCommand(actualCommand);
47
+ }
48
+ return false;
47
49
  }
48
- /**
49
- * Check if the command is specifically for nano editor (the only remote-supported editor currently)
50
- */
51
- export function isNanoEditor(command) {
52
- const trimmed = command.trim();
53
- const parts = trimmed.split(/\s+/);
54
- let baseCommand = parts[0].toLowerCase();
55
- // Handle sudo/doas prefix
56
- if (baseCommand === 'sudo' || baseCommand === 'doas') {
57
- baseCommand = parts[1]?.toLowerCase() || '';
58
- }
59
- return baseCommand === 'nano' || baseCommand === 'pico'; // pico is often aliased to nano
50
+ function isNanoEditor(command) {
51
+ const trimmed = command.trim();
52
+ const parts = trimmed.split(/\s+/);
53
+ let baseCommand = parts[0].toLowerCase();
54
+ if (baseCommand === "sudo" || baseCommand === "doas") {
55
+ baseCommand = parts[1]?.toLowerCase() || "";
56
+ }
57
+ return baseCommand === "nano" || baseCommand === "pico";
60
58
  }
61
- /**
62
- * Get the display name of an editor command for user-friendly messages
63
- */
64
- export function getEditorName(command) {
65
- const trimmed = command.trim();
66
- const parts = trimmed.split(/\s+/);
67
- let baseCommand = parts[0].toLowerCase();
68
- // Handle sudo/doas prefix
69
- if (baseCommand === 'sudo' || baseCommand === 'doas') {
70
- baseCommand = parts[1]?.toLowerCase() || baseCommand;
71
- }
72
- // Map to display names
73
- const displayNames = {
74
- 'vim': 'Vim',
75
- 'nvim': 'Neovim',
76
- 'vi': 'Vi',
77
- 'nano': 'Nano',
78
- 'emacs': 'Emacs',
79
- 'micro': 'Micro',
80
- 'helix': 'Helix',
81
- 'hx': 'Helix',
82
- 'pico': 'Pico',
83
- 'joe': 'Joe',
84
- 'ne': 'Ne',
85
- 'mcedit': 'Midnight Commander Editor',
86
- };
87
- return displayNames[baseCommand] || baseCommand;
59
+ function getEditorName(command) {
60
+ const trimmed = command.trim();
61
+ const parts = trimmed.split(/\s+/);
62
+ let baseCommand = parts[0].toLowerCase();
63
+ if (baseCommand === "sudo" || baseCommand === "doas") {
64
+ baseCommand = parts[1]?.toLowerCase() || baseCommand;
65
+ }
66
+ const displayNames = {
67
+ "vim": "Vim",
68
+ "nvim": "Neovim",
69
+ "vi": "Vi",
70
+ "nano": "Nano",
71
+ "emacs": "Emacs",
72
+ "micro": "Micro",
73
+ "helix": "Helix",
74
+ "hx": "Helix",
75
+ "pico": "Pico",
76
+ "joe": "Joe",
77
+ "ne": "Ne",
78
+ "mcedit": "Midnight Commander Editor"
79
+ };
80
+ return displayNames[baseCommand] || baseCommand;
88
81
  }
89
- /**
90
- * Get the shell command for the current platform.
91
- * On Windows, prefers Git Bash if available for better terminal emulation.
92
- */
93
82
  function getShellCommand() {
94
- if (os.platform() !== 'win32') {
95
- return process.env.SHELL || '/bin/bash';
96
- }
97
- // On Windows, try to find Git Bash for better terminal emulation
98
- const gitBashPath = findGitBash();
99
- if (gitBashPath) {
100
- return gitBashPath;
101
- }
102
- // Fallback to PowerShell
103
- return 'powershell.exe';
83
+ if (os.platform() !== "win32") {
84
+ return process.env.SHELL || "/bin/bash";
85
+ }
86
+ const gitBashPath = findGitBash();
87
+ if (gitBashPath) {
88
+ return gitBashPath;
89
+ }
90
+ return "powershell.exe";
104
91
  }
105
- /**
106
- * Find Git Bash on Windows. Returns null if not found.
107
- * Git Bash provides proper Unix terminal emulation for editors like nano.
108
- */
109
92
  function findGitBash() {
110
- const possiblePaths = [
111
- 'C:\\Program Files\\Git\\bin\\bash.exe',
112
- 'C:\\Program Files (x86)\\Git\\bin\\bash.exe',
113
- process.env.PROGRAMFILES ? `${process.env.PROGRAMFILES}\\Git\\bin\\bash.exe` : null,
114
- process.env['PROGRAMFILES(X86)'] ? `${process.env['PROGRAMFILES(X86)']}\\Git\\bin\\bash.exe` : null,
115
- // User-specific installation
116
- process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe` : null,
117
- ].filter(Boolean);
118
- for (const bashPath of possiblePaths) {
119
- try {
120
- const fs = require('fs');
121
- if (fs.existsSync(bashPath)) {
122
- return bashPath;
123
- }
124
- }
125
- catch {
126
- // Continue to next path
127
- }
93
+ const possiblePaths = [
94
+ "C:\\Program Files\\Git\\bin\\bash.exe",
95
+ "C:\\Program Files (x86)\\Git\\bin\\bash.exe",
96
+ process.env.PROGRAMFILES ? `${process.env.PROGRAMFILES}\\Git\\bin\\bash.exe` : null,
97
+ process.env["PROGRAMFILES(X86)"] ? `${process.env["PROGRAMFILES(X86)"]}\\Git\\bin\\bash.exe` : null,
98
+ // User-specific installation
99
+ process.env.LOCALAPPDATA ? `${process.env.LOCALAPPDATA}\\Programs\\Git\\bin\\bash.exe` : null
100
+ ].filter(Boolean);
101
+ for (const bashPath of possiblePaths) {
102
+ try {
103
+ const fs = require2("fs");
104
+ if (fs.existsSync(bashPath)) {
105
+ return bashPath;
106
+ }
107
+ } catch {
128
108
  }
129
- return null;
109
+ }
110
+ return null;
130
111
  }
131
- /**
132
- * Check if we should use bash-style arguments for the shell
133
- */
134
112
  function usesBashArgs(shell) {
135
- return shell.includes('bash') || shell.includes('sh');
113
+ return shell.includes("bash") || shell.includes("sh");
136
114
  }
137
- /**
138
- * Common terminal reset sequences for cleanup after editor exits
139
- */
140
115
  function getTerminalResetSequences() {
141
- return [
142
- '\x1b[?1049l', // Exit alternate screen buffer
143
- '\x1b[?25l', // HIDE cursor (let Ink show it in the right place)
144
- '\x1b[0m', // Reset text attributes (colors, bold, etc.)
145
- '\x1b[?1000l', // Disable mouse tracking (X10)
146
- '\x1b[?1002l', // Disable mouse button tracking
147
- '\x1b[?1003l', // Disable mouse any-event tracking
148
- '\x1b[?1006l', // Disable SGR mouse mode
149
- '\x1b[?2004l', // Disable bracketed paste mode
150
- '\x1b[?1u', // Disable CSI u mode (extended key reporting) - some terminals
151
- '\x1b[>4;0m', // Disable modifyOtherKeys mode
152
- '\x1b[?66l', // Disable application keypad mode
153
- '\x1b[?1l', // Disable cursor keys application mode
154
- '\x1bc', // Full terminal reset (RIS - Reset to Initial State)
155
- '\x1b[?25l', // Hide cursor again after reset (reset shows it)
156
- ].join('');
116
+ return [
117
+ "\x1B[?1049l",
118
+ // Exit alternate screen buffer
119
+ "\x1B[?25l",
120
+ // HIDE cursor (let Ink show it in the right place)
121
+ "\x1B[0m",
122
+ // Reset text attributes (colors, bold, etc.)
123
+ "\x1B[?1000l",
124
+ // Disable mouse tracking (X10)
125
+ "\x1B[?1002l",
126
+ // Disable mouse button tracking
127
+ "\x1B[?1003l",
128
+ // Disable mouse any-event tracking
129
+ "\x1B[?1006l",
130
+ // Disable SGR mouse mode
131
+ "\x1B[?2004l",
132
+ // Disable bracketed paste mode
133
+ "\x1B[?1u",
134
+ // Disable CSI u mode (extended key reporting) - some terminals
135
+ "\x1B[>4;0m",
136
+ // Disable modifyOtherKeys mode
137
+ "\x1B[?66l",
138
+ // Disable application keypad mode
139
+ "\x1B[?1l",
140
+ // Disable cursor keys application mode
141
+ "\x1Bc",
142
+ // Full terminal reset (RIS - Reset to Initial State)
143
+ "\x1B[?25l"
144
+ // Hide cursor again after reset (reset shows it)
145
+ ].join("");
157
146
  }
158
- /**
159
- * Common setup for interactive editor: raw stdin mode and handlers
160
- */
161
147
  function setupInteractiveMode(ptyProcess, onExit) {
162
- let isRunning = true;
163
- // Save original stdin settings
164
- const wasRaw = process.stdin.isRaw;
165
- // Set stdin to raw mode for direct key passthrough
148
+ let isRunning = true;
149
+ const wasRaw = process.stdin.isRaw;
150
+ if (process.stdin.isTTY) {
151
+ process.stdin.setRawMode(true);
152
+ }
153
+ process.stdin.resume();
154
+ const stdinHandler = (data) => {
155
+ if (isRunning) {
156
+ ptyProcess.write(data.toString());
157
+ }
158
+ };
159
+ process.stdin.on("data", stdinHandler);
160
+ ptyProcess.onData((data) => {
161
+ if (isRunning) {
162
+ process.stdout.write(data);
163
+ }
164
+ });
165
+ const resizeHandler = () => {
166
+ if (isRunning) {
167
+ const newCols = process.stdout.columns || 80;
168
+ const newRows = process.stdout.rows || 24;
169
+ try {
170
+ ptyProcess.resize(newCols, newRows);
171
+ } catch (e) {
172
+ }
173
+ }
174
+ };
175
+ process.stdout.on("resize", resizeHandler);
176
+ ptyProcess.onExit(({ exitCode }) => {
177
+ isRunning = false;
178
+ process.stdin.removeListener("data", stdinHandler);
179
+ process.stdout.removeListener("resize", resizeHandler);
166
180
  if (process.stdin.isTTY) {
167
- process.stdin.setRawMode(true);
181
+ process.stdin.setRawMode(wasRaw ?? false);
168
182
  }
169
- process.stdin.resume();
170
- // Pipe stdin to PTY (user keys -> editor)
171
- const stdinHandler = (data) => {
172
- if (isRunning) {
173
- ptyProcess.write(data.toString());
183
+ process.stdout.write(getTerminalResetSequences());
184
+ setTimeout(() => {
185
+ onExit(exitCode);
186
+ }, 200);
187
+ });
188
+ return {
189
+ cleanup: () => {
190
+ process.stdin.removeListener("data", stdinHandler);
191
+ process.stdout.removeListener("resize", resizeHandler);
192
+ if (process.stdin.isTTY) {
193
+ process.stdin.setRawMode(wasRaw ?? false);
194
+ }
195
+ },
196
+ kill: () => {
197
+ if (isRunning) {
198
+ isRunning = false;
199
+ try {
200
+ ptyProcess.kill();
201
+ } catch (e) {
174
202
  }
175
- };
176
- process.stdin.on('data', stdinHandler);
177
- // Pipe PTY output to stdout (editor display -> terminal)
178
- ptyProcess.onData((data) => {
179
- if (isRunning) {
180
- process.stdout.write(data);
203
+ }
204
+ }
205
+ };
206
+ }
207
+ function runInteractiveEditor(command, cwd, onExit) {
208
+ const shell = getShellCommand();
209
+ const isWindows = os.platform() === "win32";
210
+ const isBash = usesBashArgs(shell);
211
+ const args = isBash ? ["-c", command] : isWindows ? ["-Command", command] : ["-c", command];
212
+ const cols = process.stdout.columns || 80;
213
+ const rows = process.stdout.rows || 24;
214
+ const enterAlternateBuffer = [
215
+ "\x1B[?1049h",
216
+ // Enter alternate screen buffer
217
+ "\x1B[2J",
218
+ // Clear entire screen
219
+ "\x1B[H"
220
+ // Move cursor to home position
221
+ ].join("");
222
+ process.stdout.write(enterAlternateBuffer);
223
+ const ptyProcess = nodePty.spawn(shell, args, {
224
+ name: isWindows ? "cygwin" : "xterm-256color",
225
+ cols,
226
+ rows,
227
+ cwd,
228
+ env: {
229
+ ...process.env,
230
+ // Use cygwin TERM on Windows for better nano compatibility
231
+ TERM: isWindows ? "cygwin" : "xterm-256color",
232
+ COLORTERM: "truecolor"
233
+ }
234
+ });
235
+ let isRunning = true;
236
+ const wasRaw = process.stdin.isRaw;
237
+ if (process.stdin.isTTY) {
238
+ process.stdin.setRawMode(true);
239
+ }
240
+ process.stdin.resume();
241
+ const stdinHandler = (data) => {
242
+ if (isRunning) {
243
+ ptyProcess.write(data.toString());
244
+ }
245
+ };
246
+ process.stdin.on("data", stdinHandler);
247
+ ptyProcess.onData((data) => {
248
+ if (isRunning) {
249
+ process.stdout.write(data);
250
+ }
251
+ });
252
+ const resizeHandler = () => {
253
+ if (isRunning) {
254
+ const newCols = process.stdout.columns || 80;
255
+ const newRows = process.stdout.rows || 24;
256
+ try {
257
+ ptyProcess.resize(newCols, newRows);
258
+ } catch (e) {
259
+ }
260
+ }
261
+ };
262
+ process.stdout.on("resize", resizeHandler);
263
+ ptyProcess.onExit(({ exitCode }) => {
264
+ isRunning = false;
265
+ process.stdin.removeListener("data", stdinHandler);
266
+ process.stdout.removeListener("resize", resizeHandler);
267
+ if (process.stdin.isTTY) {
268
+ process.stdin.setRawMode(wasRaw ?? false);
269
+ }
270
+ process.stdout.write(getTerminalResetSequences());
271
+ setTimeout(() => {
272
+ onExit(exitCode);
273
+ }, 200);
274
+ });
275
+ return {
276
+ kill: () => {
277
+ if (isRunning) {
278
+ isRunning = false;
279
+ try {
280
+ ptyProcess.kill();
281
+ } catch (e) {
282
+ }
283
+ }
284
+ }
285
+ };
286
+ }
287
+ function runWSLEditor(distribution, command, cwd, onExit) {
288
+ const cols = process.stdout.columns || 80;
289
+ const rows = process.stdout.rows || 24;
290
+ const wslArgs = [
291
+ "-d",
292
+ distribution,
293
+ "--",
294
+ "bash",
295
+ "-c",
296
+ `cd "${cwd}" && ${command}`
297
+ ];
298
+ const ptyProcess = nodePty.spawn("wsl.exe", wslArgs, {
299
+ name: "xterm-256color",
300
+ cols,
301
+ rows,
302
+ cwd: process.cwd(),
303
+ // Use current Windows cwd
304
+ env: {
305
+ ...process.env,
306
+ TERM: "xterm-256color",
307
+ COLORTERM: "truecolor"
308
+ }
309
+ });
310
+ const { kill } = setupInteractiveMode(ptyProcess, onExit);
311
+ return { kill };
312
+ }
313
+ function runWSLCommand(distribution, command, cwd, onData, onExit, initialCols, initialRows) {
314
+ const cols = initialCols || process.stdout.columns || 80;
315
+ const rows = initialRows || process.stdout.rows || 24;
316
+ const wslArgs = [
317
+ "-d",
318
+ distribution,
319
+ "--",
320
+ "bash",
321
+ "-c",
322
+ `cd "${cwd}" && ${command}`
323
+ ];
324
+ const ptyProcess = nodePty.spawn("wsl.exe", wslArgs, {
325
+ name: "xterm-256color",
326
+ cols,
327
+ rows,
328
+ cwd: process.cwd(),
329
+ env: {
330
+ ...process.env,
331
+ TERM: "xterm-256color",
332
+ COLORTERM: "truecolor"
333
+ }
334
+ });
335
+ let isRunning = true;
336
+ let hasExited = false;
337
+ const finalizeExit = (exitCode) => {
338
+ if (hasExited) return;
339
+ hasExited = true;
340
+ isRunning = false;
341
+ onExit(exitCode);
342
+ };
343
+ ptyProcess.onData((data) => {
344
+ if (isRunning) {
345
+ onData(data);
346
+ }
347
+ });
348
+ ptyProcess.onExit(({ exitCode }) => {
349
+ finalizeExit(exitCode);
350
+ });
351
+ return {
352
+ write: (data) => {
353
+ if (isRunning) {
354
+ ptyProcess.write(data);
355
+ }
356
+ },
357
+ kill: () => {
358
+ if (!isRunning || hasExited) {
359
+ return;
360
+ }
361
+ isRunning = false;
362
+ try {
363
+ ptyProcess.kill();
364
+ } catch (e) {
365
+ }
366
+ setTimeout(() => {
367
+ finalizeExit(130);
368
+ }, 150);
369
+ },
370
+ resize: (cols2, rows2) => {
371
+ if (isRunning) {
372
+ try {
373
+ ptyProcess.resize(cols2, rows2);
374
+ } catch (e) {
375
+ }
376
+ }
377
+ },
378
+ isRunning: () => isRunning
379
+ };
380
+ }
381
+ function runDockerCommand(containerId, command, cwd, onData, onExit, initialCols, initialRows) {
382
+ const cols = initialCols || process.stdout.columns || 80;
383
+ const rows = initialRows || process.stdout.rows || 24;
384
+ const dockerArgs = [
385
+ "exec",
386
+ "-it",
387
+ containerId,
388
+ "bash",
389
+ "-c",
390
+ `cd "${cwd}" && ${command}`
391
+ ];
392
+ const ptyProcess = nodePty.spawn("docker", dockerArgs, {
393
+ name: "xterm-256color",
394
+ cols,
395
+ rows,
396
+ cwd: process.cwd(),
397
+ env: {
398
+ ...process.env,
399
+ TERM: "xterm-256color",
400
+ COLORTERM: "truecolor"
401
+ }
402
+ });
403
+ let isRunning = true;
404
+ let hasExited = false;
405
+ const finalizeExit = (exitCode) => {
406
+ if (hasExited) return;
407
+ hasExited = true;
408
+ isRunning = false;
409
+ onExit(exitCode);
410
+ };
411
+ ptyProcess.onData((data) => {
412
+ if (isRunning) {
413
+ onData(data);
414
+ }
415
+ });
416
+ ptyProcess.onExit(({ exitCode }) => {
417
+ finalizeExit(exitCode);
418
+ });
419
+ return {
420
+ write: (data) => {
421
+ if (isRunning) {
422
+ ptyProcess.write(data);
423
+ }
424
+ },
425
+ kill: () => {
426
+ if (!isRunning || hasExited) {
427
+ return;
428
+ }
429
+ isRunning = false;
430
+ try {
431
+ ptyProcess.kill();
432
+ } catch (e) {
433
+ }
434
+ setTimeout(() => {
435
+ finalizeExit(130);
436
+ }, 150);
437
+ },
438
+ resize: (cols2, rows2) => {
439
+ if (isRunning) {
440
+ try {
441
+ ptyProcess.resize(cols2, rows2);
442
+ } catch (e) {
443
+ }
444
+ }
445
+ },
446
+ isRunning: () => isRunning
447
+ };
448
+ }
449
+ function runDockerEditor(containerId, command, cwd, onExit) {
450
+ const cols = process.stdout.columns || 80;
451
+ const rows = process.stdout.rows || 24;
452
+ const dockerArgs = [
453
+ "exec",
454
+ "-it",
455
+ containerId,
456
+ "bash",
457
+ "-c",
458
+ `cd "${cwd}" && ${command}`
459
+ ];
460
+ const ptyProcess = nodePty.spawn("docker", dockerArgs, {
461
+ name: "xterm-256color",
462
+ cols,
463
+ rows,
464
+ cwd: process.cwd(),
465
+ env: {
466
+ ...process.env,
467
+ TERM: "xterm-256color",
468
+ COLORTERM: "truecolor"
469
+ }
470
+ });
471
+ const { kill } = setupInteractiveMode(ptyProcess, onExit);
472
+ return { kill };
473
+ }
474
+ function runSSHEditor(sshClient, command, cwd, onExit) {
475
+ let isRunning = true;
476
+ let stream = null;
477
+ const wasRaw = process.stdin.isRaw;
478
+ const cols = process.stdout.columns || 80;
479
+ const rows = process.stdout.rows || 24;
480
+ sshClient.shell(
481
+ {
482
+ term: "xterm-256color",
483
+ cols,
484
+ rows
485
+ },
486
+ (err, shellStream) => {
487
+ if (err) {
488
+ logError("Failed to open SSH shell", err);
489
+ onExit(1);
490
+ return;
491
+ }
492
+ stream = shellStream;
493
+ if (process.stdin.isTTY) {
494
+ process.stdin.setRawMode(true);
495
+ }
496
+ process.stdin.resume();
497
+ const stdinHandler = (data) => {
498
+ if (isRunning && stream) {
499
+ stream.write(data);
181
500
  }
182
- });
183
- // Handle terminal resize
184
- const resizeHandler = () => {
501
+ };
502
+ process.stdin.on("data", stdinHandler);
503
+ stream.on("data", (data) => {
185
504
  if (isRunning) {
186
- const newCols = process.stdout.columns || 80;
187
- const newRows = process.stdout.rows || 24;
188
- try {
189
- ptyProcess.resize(newCols, newRows);
190
- }
191
- catch (e) {
192
- // Ignore resize errors
193
- }
505
+ process.stdout.write(data);
194
506
  }
195
- };
196
- process.stdout.on('resize', resizeHandler);
197
- // Handle PTY exit
198
- ptyProcess.onExit(({ exitCode }) => {
507
+ });
508
+ const resizeHandler = () => {
509
+ if (isRunning && stream) {
510
+ const newCols = process.stdout.columns || 80;
511
+ const newRows = process.stdout.rows || 24;
512
+ try {
513
+ stream.setWindow(newRows, newCols, 0, 0);
514
+ } catch (e) {
515
+ }
516
+ }
517
+ };
518
+ process.stdout.on("resize", resizeHandler);
519
+ stream.on("close", () => {
199
520
  isRunning = false;
200
- // CRITICAL: Remove our stdin handler FIRST
201
- process.stdin.removeListener('data', stdinHandler);
202
- process.stdout.removeListener('resize', resizeHandler);
203
- // Restore stdin to original raw mode setting
521
+ process.stdin.removeListener("data", stdinHandler);
522
+ process.stdout.removeListener("resize", resizeHandler);
204
523
  if (process.stdin.isTTY) {
205
- process.stdin.setRawMode(wasRaw ?? false);
524
+ process.stdin.setRawMode(wasRaw ?? false);
206
525
  }
207
- // COMPREHENSIVE TERMINAL RESET
208
526
  process.stdout.write(getTerminalResetSequences());
209
- // Give terminal time to process reset sequences
210
527
  setTimeout(() => {
211
- onExit(exitCode);
528
+ onExit(0);
212
529
  }, 200);
213
- });
214
- return {
215
- cleanup: () => {
216
- process.stdin.removeListener('data', stdinHandler);
217
- process.stdout.removeListener('resize', resizeHandler);
218
- if (process.stdin.isTTY) {
219
- process.stdin.setRawMode(wasRaw ?? false);
220
- }
221
- },
222
- kill: () => {
223
- if (isRunning) {
224
- isRunning = false;
225
- try {
226
- ptyProcess.kill();
227
- }
228
- catch (e) {
229
- // Ignore kill errors
230
- }
231
- }
530
+ });
531
+ stream.write(`cd "${cwd}" && ${command}; exit
532
+ `);
533
+ }
534
+ );
535
+ return {
536
+ kill: () => {
537
+ if (isRunning) {
538
+ isRunning = false;
539
+ if (stream) {
540
+ try {
541
+ stream.close();
542
+ } catch (e) {
543
+ }
232
544
  }
233
- };
545
+ }
546
+ }
547
+ };
234
548
  }
235
- /**
236
- * Run an interactive editor with full terminal control (LOCAL mode).
237
- * This function:
238
- * 1. Clears the screen and enters alternate screen buffer
239
- * 2. Spawns a PTY process
240
- * 3. Pipes stdin directly to the PTY (raw mode)
241
- * 4. Pipes PTY output directly to stdout
242
- * 5. Handles cleanup on exit
243
- *
244
- * Uses alternate screen buffer to prevent chat history from showing through.
245
- */
246
- export function runInteractiveEditor(command, cwd, onExit) {
247
- const shell = getShellCommand();
248
- const isWindows = os.platform() === 'win32';
249
- // Use bash-style args for Git Bash, PowerShell-style only if falling back to PowerShell
250
- const isBash = usesBashArgs(shell);
251
- const args = isBash ? ['-c', command] : (isWindows ? ['-Command', command] : ['-c', command]);
252
- // Get terminal dimensions
253
- const cols = process.stdout.columns || 80;
254
- const rows = process.stdout.rows || 24;
255
- // Enter alternate screen buffer and clear screen to hide chat history
256
- // This combined with cygwin terminal type provides proper display on Windows
257
- const enterAlternateBuffer = [
258
- '\x1b[?1049h', // Enter alternate screen buffer
259
- '\x1b[2J', // Clear entire screen
260
- '\x1b[H', // Move cursor to home position
261
- ].join('');
262
- process.stdout.write(enterAlternateBuffer);
263
- // Spawn PTY process - use 'cygwin' terminal type on Windows for better compatibility
264
- // 'xterm-256color' can cause issues with some Windows terminal configurations
265
- const ptyProcess = nodePty.spawn(shell, args, {
266
- name: isWindows ? 'cygwin' : 'xterm-256color',
267
- cols,
268
- rows,
269
- cwd,
270
- env: {
271
- ...process.env,
272
- // Use cygwin TERM on Windows for better nano compatibility
273
- TERM: isWindows ? 'cygwin' : 'xterm-256color',
274
- COLORTERM: 'truecolor',
275
- },
276
- });
277
- let isRunning = true;
278
- // Save original stdin settings
279
- const wasRaw = process.stdin.isRaw;
280
- // Set stdin to raw mode for direct key passthrough
281
- if (process.stdin.isTTY) {
549
+ function runNestedDockerSSHEditor(sshClient, containerId, command, cwd, onExit) {
550
+ let isRunning = true;
551
+ let stream = null;
552
+ const wasRaw = process.stdin.isRaw;
553
+ const cols = process.stdout.columns || 80;
554
+ const rows = process.stdout.rows || 24;
555
+ const enterAlternateBuffer = [
556
+ "\x1B[?1049h",
557
+ // Enter alternate screen buffer
558
+ "\x1B[2J",
559
+ // Clear entire screen
560
+ "\x1B[H"
561
+ // Move cursor to home position
562
+ ].join("");
563
+ process.stdout.write(enterAlternateBuffer);
564
+ sshClient.shell(
565
+ {
566
+ term: "xterm-256color",
567
+ cols,
568
+ rows
569
+ },
570
+ (err, shellStream) => {
571
+ if (err) {
572
+ logError("Failed to open SSH shell for nested Docker editor", err);
573
+ onExit(1);
574
+ return;
575
+ }
576
+ stream = shellStream;
577
+ if (process.stdin.isTTY) {
282
578
  process.stdin.setRawMode(true);
283
- }
284
- process.stdin.resume();
285
- // Pipe stdin to PTY (user keys -> editor)
286
- const stdinHandler = (data) => {
287
- if (isRunning) {
288
- ptyProcess.write(data.toString());
579
+ }
580
+ process.stdin.resume();
581
+ const stdinHandler = (data) => {
582
+ if (isRunning && stream) {
583
+ stream.write(data);
289
584
  }
290
- };
291
- process.stdin.on('data', stdinHandler);
292
- // Pipe PTY output to stdout (editor display -> terminal)
293
- ptyProcess.onData((data) => {
585
+ };
586
+ process.stdin.on("data", stdinHandler);
587
+ stream.on("data", (data) => {
294
588
  if (isRunning) {
295
- process.stdout.write(data);
589
+ process.stdout.write(data);
296
590
  }
297
- });
298
- // Handle terminal resize
299
- const resizeHandler = () => {
300
- if (isRunning) {
301
- const newCols = process.stdout.columns || 80;
302
- const newRows = process.stdout.rows || 24;
303
- try {
304
- ptyProcess.resize(newCols, newRows);
305
- }
306
- catch (e) {
307
- // Ignore resize errors
308
- }
591
+ });
592
+ const resizeHandler = () => {
593
+ if (isRunning && stream) {
594
+ const newCols = process.stdout.columns || 80;
595
+ const newRows = process.stdout.rows || 24;
596
+ try {
597
+ stream.setWindow(newRows, newCols, 0, 0);
598
+ } catch (e) {
599
+ }
309
600
  }
310
- };
311
- process.stdout.on('resize', resizeHandler);
312
- // Handle PTY exit
313
- ptyProcess.onExit(({ exitCode }) => {
601
+ };
602
+ process.stdout.on("resize", resizeHandler);
603
+ stream.on("close", () => {
314
604
  isRunning = false;
315
- // CRITICAL: Remove our stdin handler FIRST
316
- process.stdin.removeListener('data', stdinHandler);
317
- process.stdout.removeListener('resize', resizeHandler);
318
- // Restore stdin to original raw mode setting
605
+ process.stdin.removeListener("data", stdinHandler);
606
+ process.stdout.removeListener("resize", resizeHandler);
319
607
  if (process.stdin.isTTY) {
320
- process.stdin.setRawMode(wasRaw ?? false);
608
+ process.stdin.setRawMode(wasRaw ?? false);
321
609
  }
322
- // COMPREHENSIVE TERMINAL RESET
323
610
  process.stdout.write(getTerminalResetSequences());
324
- // Give terminal time to process reset sequences
325
611
  setTimeout(() => {
326
- onExit(exitCode);
612
+ onExit(0);
327
613
  }, 200);
328
- });
329
- return {
330
- kill: () => {
331
- if (isRunning) {
332
- isRunning = false;
333
- try {
334
- ptyProcess.kill();
335
- }
336
- catch (e) {
337
- // Ignore kill errors
338
- }
339
- }
340
- }
341
- };
342
- }
343
- /**
344
- * Run an interactive editor in WSL session via node-pty.
345
- * Uses wsl.exe to execute the editor command in the specified distribution.
346
- */
347
- export function runWSLEditor(distribution, command, cwd, onExit) {
348
- // Get terminal dimensions
349
- const cols = process.stdout.columns || 80;
350
- const rows = process.stdout.rows || 24;
351
- // Build WSL command - cd to directory and run editor
352
- // wsl.exe -d <distro> -- bash -c "cd <path> && <command>"
353
- const wslArgs = [
354
- '-d', distribution,
355
- '--',
356
- 'bash', '-c',
357
- `cd "${cwd}" && ${command}`
358
- ];
359
- // Spawn PTY process with wsl.exe
360
- const ptyProcess = nodePty.spawn('wsl.exe', wslArgs, {
361
- name: 'xterm-256color',
362
- cols,
363
- rows,
364
- cwd: process.cwd(), // Use current Windows cwd
365
- env: {
366
- ...process.env,
367
- TERM: 'xterm-256color',
368
- COLORTERM: 'truecolor',
369
- },
370
- });
371
- const { kill } = setupInteractiveMode(ptyProcess, onExit);
372
- return { kill };
373
- }
374
- /**
375
- * Run a command in WSL session via node-pty with streaming output.
376
- * Unlike runWSLEditor, this doesn't take over the terminal - it streams output to a callback.
377
- * This is essential for sudo commands that need TTY for password prompts.
378
- */
379
- export function runWSLCommand(distribution, command, cwd, onData, onExit, initialCols, initialRows) {
380
- // Get terminal dimensions - use provided values or fall back to process.stdout
381
- // Constrained dimensions help with proper escape sequence handling in UI display
382
- const cols = initialCols || process.stdout.columns || 80;
383
- const rows = initialRows || process.stdout.rows || 24;
384
- // Build WSL command - cd to directory and run command
385
- const wslArgs = [
386
- '-d', distribution,
387
- '--',
388
- 'bash', '-c',
389
- `cd "${cwd}" && ${command}`
390
- ];
391
- // Spawn PTY process with wsl.exe
392
- const ptyProcess = nodePty.spawn('wsl.exe', wslArgs, {
393
- name: 'xterm-256color',
394
- cols,
395
- rows,
396
- cwd: process.cwd(),
397
- env: {
398
- ...process.env,
399
- TERM: 'xterm-256color',
400
- COLORTERM: 'truecolor',
401
- },
402
- });
403
- let isRunning = true;
404
- // Stream output to callback
405
- ptyProcess.onData((data) => {
406
- if (isRunning) {
407
- onData(data);
408
- }
409
- });
410
- // Handle exit
411
- ptyProcess.onExit(({ exitCode }) => {
614
+ });
615
+ const escapedCwd = cwd.replace(/"/g, '\\"');
616
+ const escapedCommand = command.replace(/"/g, '\\"');
617
+ const dockerExecCommand = `docker exec -it ${containerId} bash -c "cd \\"${escapedCwd}\\" && ${escapedCommand}"; exit
618
+ `;
619
+ stream.write(dockerExecCommand);
620
+ }
621
+ );
622
+ return {
623
+ kill: () => {
624
+ if (isRunning) {
412
625
  isRunning = false;
413
- onExit(exitCode);
414
- });
415
- return {
416
- write: (data) => {
417
- if (isRunning) {
418
- ptyProcess.write(data);
419
- }
420
- },
421
- kill: () => {
422
- if (isRunning) {
423
- isRunning = false;
424
- try {
425
- ptyProcess.kill();
426
- }
427
- catch (e) {
428
- // Ignore kill errors
429
- }
430
- }
431
- },
432
- resize: (cols, rows) => {
433
- if (isRunning) {
434
- try {
435
- ptyProcess.resize(cols, rows);
436
- }
437
- catch (e) {
438
- // Ignore resize errors
439
- }
440
- }
441
- },
442
- isRunning: () => isRunning
443
- };
444
- }
445
- /**
446
- * Run a command in Docker container via node-pty with streaming output.
447
- * Unlike runDockerEditor, this doesn't take over the terminal - it streams output to a callback.
448
- * This is essential for sudo commands that need TTY for password prompts.
449
- */
450
- export function runDockerCommand(containerId, command, cwd, onData, onExit, initialCols, initialRows) {
451
- // Get terminal dimensions - use provided values or fall back to process.stdout
452
- // Constrained dimensions help with proper escape sequence handling in UI display
453
- const cols = initialCols || process.stdout.columns || 80;
454
- const rows = initialRows || process.stdout.rows || 24;
455
- // Build docker exec command
456
- const dockerArgs = [
457
- 'exec',
458
- '-it',
459
- containerId,
460
- 'bash', '-c',
461
- `cd "${cwd}" && ${command}`
462
- ];
463
- // Spawn PTY process with docker
464
- const ptyProcess = nodePty.spawn('docker', dockerArgs, {
465
- name: 'xterm-256color',
466
- cols,
467
- rows,
468
- cwd: process.cwd(),
469
- env: {
470
- ...process.env,
471
- TERM: 'xterm-256color',
472
- COLORTERM: 'truecolor',
473
- },
474
- });
475
- let isRunning = true;
476
- // Stream output to callback
477
- ptyProcess.onData((data) => {
478
- if (isRunning) {
479
- onData(data);
626
+ if (stream) {
627
+ try {
628
+ stream.close();
629
+ } catch (e) {
630
+ }
480
631
  }
481
- });
482
- // Handle exit
483
- ptyProcess.onExit(({ exitCode }) => {
484
- isRunning = false;
485
- onExit(exitCode);
486
- });
487
- return {
488
- write: (data) => {
489
- if (isRunning) {
490
- ptyProcess.write(data);
491
- }
492
- },
493
- kill: () => {
494
- if (isRunning) {
495
- isRunning = false;
496
- try {
497
- ptyProcess.kill();
498
- }
499
- catch (e) {
500
- // Ignore kill errors
501
- }
502
- }
503
- },
504
- resize: (cols, rows) => {
505
- if (isRunning) {
506
- try {
507
- ptyProcess.resize(cols, rows);
508
- }
509
- catch (e) {
510
- // Ignore resize errors
511
- }
512
- }
513
- },
514
- isRunning: () => isRunning
515
- };
516
- }
517
- /**
518
- * Run an interactive editor in Docker container via node-pty.
519
- * Uses docker exec -it to execute the editor command in the container.
520
- */
521
- export function runDockerEditor(containerId, command, cwd, onExit) {
522
- // Get terminal dimensions
523
- const cols = process.stdout.columns || 80;
524
- const rows = process.stdout.rows || 24;
525
- // Build docker exec command
526
- // docker exec -it <container> bash -c "cd <path> && <command>"
527
- const dockerArgs = [
528
- 'exec',
529
- '-it',
530
- containerId,
531
- 'bash', '-c',
532
- `cd "${cwd}" && ${command}`
533
- ];
534
- // Spawn PTY process with docker
535
- const ptyProcess = nodePty.spawn('docker', dockerArgs, {
536
- name: 'xterm-256color',
537
- cols,
538
- rows,
539
- cwd: process.cwd(),
540
- env: {
541
- ...process.env,
542
- TERM: 'xterm-256color',
543
- COLORTERM: 'truecolor',
544
- },
545
- });
546
- const { kill } = setupInteractiveMode(ptyProcess, onExit);
547
- return { kill };
632
+ }
633
+ }
634
+ };
548
635
  }
549
- /**
550
- * Run an interactive editor in SSH session via ssh2's interactive shell.
551
- * This is more complex as we need to use the ssh2 client's shell() method
552
- * instead of exec() to get a proper interactive PTY.
553
- */
554
- export function runSSHEditor(sshClient, // ssh2 Client
555
- command, cwd, onExit) {
556
- let isRunning = true;
557
- let stream = null;
558
- // Save original stdin settings
559
- const wasRaw = process.stdin.isRaw;
560
- // Get terminal dimensions
561
- const cols = process.stdout.columns || 80;
562
- const rows = process.stdout.rows || 24;
563
- // Request an interactive shell from the SSH server
564
- sshClient.shell({
565
- term: 'xterm-256color',
636
+ function runSSHCommand(sshClient, command, cwd, onData, onExit, initialCols, initialRows) {
637
+ let isRunning = true;
638
+ let stream = null;
639
+ let hasExited = false;
640
+ let killRequested = false;
641
+ const finalizeExit = (exitCode) => {
642
+ if (hasExited) return;
643
+ hasExited = true;
644
+ isRunning = false;
645
+ onExit(exitCode);
646
+ };
647
+ const cols = initialCols || process.stdout.columns || 80;
648
+ const rows = initialRows || process.stdout.rows || 24;
649
+ const fullCommand = `cd "${cwd}" && ${command}`;
650
+ sshClient.exec(
651
+ fullCommand,
652
+ {
653
+ pty: {
654
+ term: "xterm-256color",
566
655
  cols,
567
656
  rows,
568
- }, (err, shellStream) => {
569
- if (err) {
570
- logError('Failed to open SSH shell', err);
571
- onExit(1);
572
- return;
573
- }
574
- stream = shellStream;
575
- // Set stdin to raw mode for direct key passthrough
576
- if (process.stdin.isTTY) {
577
- process.stdin.setRawMode(true);
657
+ modes: {
658
+ ECHO: 0
659
+ // Disable echo to prevent duplicate output
578
660
  }
579
- process.stdin.resume();
580
- // Pipe stdin to SSH stream (user keys -> remote shell)
581
- const stdinHandler = (data) => {
582
- if (isRunning && stream) {
583
- stream.write(data);
584
- }
585
- };
586
- process.stdin.on('data', stdinHandler);
587
- // Pipe SSH stream output to stdout (remote -> terminal)
588
- stream.on('data', (data) => {
589
- if (isRunning) {
590
- process.stdout.write(data);
591
- }
592
- });
593
- // Handle terminal resize
594
- const resizeHandler = () => {
595
- if (isRunning && stream) {
596
- const newCols = process.stdout.columns || 80;
597
- const newRows = process.stdout.rows || 24;
598
- try {
599
- stream.setWindow(newRows, newCols, 0, 0);
600
- }
601
- catch (e) {
602
- // Ignore resize errors
603
- }
604
- }
605
- };
606
- process.stdout.on('resize', resizeHandler);
607
- // Handle stream close
608
- stream.on('close', () => {
609
- isRunning = false;
610
- // CRITICAL: Remove our stdin handler FIRST
611
- process.stdin.removeListener('data', stdinHandler);
612
- process.stdout.removeListener('resize', resizeHandler);
613
- // Restore stdin to original raw mode setting
614
- if (process.stdin.isTTY) {
615
- process.stdin.setRawMode(wasRaw ?? false);
616
- }
617
- // COMPREHENSIVE TERMINAL RESET
618
- process.stdout.write(getTerminalResetSequences());
619
- // Give terminal time to process reset sequences
620
- setTimeout(() => {
621
- onExit(0);
622
- }, 200);
623
- });
624
- // Send the command to the shell: cd to directory and run editor
625
- // Note: We send the command with exit so shell closes after editor exits
626
- stream.write(`cd "${cwd}" && ${command}; exit\n`);
627
- });
628
- return {
629
- kill: () => {
630
- if (isRunning) {
631
- isRunning = false;
632
- if (stream) {
633
- try {
634
- stream.close();
635
- }
636
- catch (e) {
637
- // Ignore close errors
638
- }
639
- }
640
- }
661
+ }
662
+ },
663
+ (err, execStream) => {
664
+ if (err) {
665
+ logError("Failed to execute SSH command", err);
666
+ finalizeExit(1);
667
+ return;
668
+ }
669
+ stream = execStream;
670
+ if (killRequested) {
671
+ try {
672
+ stream.close();
673
+ } catch (e) {
641
674
  }
642
- };
643
- }
644
- /**
645
- * Run an interactive editor in a Docker container that is accessed through SSH.
646
- * This routes the docker exec command through the SSH session to properly access
647
- * the remote Docker daemon instead of trying to use local Docker.
648
- */
649
- export function runNestedDockerSSHEditor(sshClient, // ssh2 Client from parent SSH context
650
- containerId, command, cwd, onExit) {
651
- let isRunning = true;
652
- let stream = null;
653
- // Save original stdin settings
654
- const wasRaw = process.stdin.isRaw;
655
- // Get terminal dimensions
656
- const cols = process.stdout.columns || 80;
657
- const rows = process.stdout.rows || 24;
658
- // Enter alternate screen buffer and clear screen to hide chat history
659
- const enterAlternateBuffer = [
660
- '\x1b[?1049h', // Enter alternate screen buffer
661
- '\x1b[2J', // Clear entire screen
662
- '\x1b[H', // Move cursor to home position
663
- ].join('');
664
- process.stdout.write(enterAlternateBuffer);
665
- // Request an interactive shell from the SSH server
666
- sshClient.shell({
667
- term: 'xterm-256color',
668
- cols,
669
- rows,
670
- }, (err, shellStream) => {
671
- if (err) {
672
- logError('Failed to open SSH shell for nested Docker editor', err);
673
- onExit(1);
674
- return;
675
+ finalizeExit(130);
676
+ return;
677
+ }
678
+ stream.on("data", (data) => {
679
+ if (isRunning) {
680
+ onData(data.toString());
675
681
  }
676
- stream = shellStream;
677
- // Set stdin to raw mode for direct key passthrough
678
- if (process.stdin.isTTY) {
679
- process.stdin.setRawMode(true);
682
+ });
683
+ stream.on("close", (code) => {
684
+ finalizeExit(code || 0);
685
+ });
686
+ }
687
+ );
688
+ return {
689
+ write: (data) => {
690
+ if (isRunning && stream) {
691
+ stream.write(data);
692
+ }
693
+ },
694
+ kill: () => {
695
+ if (!isRunning || hasExited) {
696
+ return;
697
+ }
698
+ killRequested = true;
699
+ isRunning = false;
700
+ if (stream) {
701
+ try {
702
+ stream.close();
703
+ } catch (e) {
680
704
  }
681
- process.stdin.resume();
682
- // Pipe stdin to SSH stream (user keys -> remote shell -> docker)
683
- const stdinHandler = (data) => {
684
- if (isRunning && stream) {
685
- stream.write(data);
686
- }
687
- };
688
- process.stdin.on('data', stdinHandler);
689
- // Pipe SSH stream output to stdout (docker -> remote shell -> terminal)
690
- stream.on('data', (data) => {
691
- if (isRunning) {
692
- process.stdout.write(data);
693
- }
694
- });
695
- // Handle terminal resize
696
- const resizeHandler = () => {
697
- if (isRunning && stream) {
698
- const newCols = process.stdout.columns || 80;
699
- const newRows = process.stdout.rows || 24;
700
- try {
701
- stream.setWindow(newRows, newCols, 0, 0);
702
- }
703
- catch (e) {
704
- // Ignore resize errors
705
- }
706
- }
707
- };
708
- process.stdout.on('resize', resizeHandler);
709
- // Handle stream close
710
- stream.on('close', () => {
711
- isRunning = false;
712
- // CRITICAL: Remove our stdin handler FIRST
713
- process.stdin.removeListener('data', stdinHandler);
714
- process.stdout.removeListener('resize', resizeHandler);
715
- // Restore stdin to original raw mode setting
716
- if (process.stdin.isTTY) {
717
- process.stdin.setRawMode(wasRaw ?? false);
718
- }
719
- // COMPREHENSIVE TERMINAL RESET
720
- process.stdout.write(getTerminalResetSequences());
721
- // Give terminal time to process reset sequences
722
- setTimeout(() => {
723
- onExit(0);
724
- }, 200);
725
- });
726
- // Build the docker exec command to run via SSH shell
727
- // Use docker exec -it for interactive TTY, cd to cwd, run command, then exit
728
- const escapedCwd = cwd.replace(/"/g, '\\"');
729
- const escapedCommand = command.replace(/"/g, '\\"');
730
- const dockerExecCommand = `docker exec -it ${containerId} bash -c "cd \\"${escapedCwd}\\" && ${escapedCommand}"; exit\n`;
731
- stream.write(dockerExecCommand);
732
- });
733
- return {
734
- kill: () => {
735
- if (isRunning) {
736
- isRunning = false;
737
- if (stream) {
738
- try {
739
- stream.close();
740
- }
741
- catch (e) {
742
- // Ignore close errors
743
- }
744
- }
745
- }
705
+ }
706
+ setTimeout(() => {
707
+ finalizeExit(130);
708
+ }, 150);
709
+ },
710
+ resize: (cols2, rows2) => {
711
+ if (isRunning && stream) {
712
+ try {
713
+ stream.setWindow(rows2, cols2, 0, 0);
714
+ } catch (e) {
746
715
  }
747
- };
716
+ }
717
+ },
718
+ isRunning: () => isRunning
719
+ };
748
720
  }
749
- /**
750
- * Run a command in SSH session via ssh2's exec with PTY for streaming output.
751
- * Uses exec() with PTY option instead of shell() to avoid login banners and command echo.
752
- * This reuses the existing SSH connection so password is not required for each command.
753
- */
754
- export function runSSHCommand(sshClient, // ssh2 Client
755
- command, cwd, onData, onExit, initialCols, initialRows) {
756
- let isRunning = true;
757
- let stream = null;
758
- // Get terminal dimensions - use provided values or fall back to process.stdout
759
- // Constrained dimensions help with proper escape sequence handling in UI display
760
- const cols = initialCols || process.stdout.columns || 80;
761
- const rows = initialRows || process.stdout.rows || 24;
762
- // Build the full command with cd
763
- const fullCommand = `cd "${cwd}" && ${command}`;
764
- // Use exec() with PTY option instead of shell()
765
- // This runs a single command with PTY support but without login shell overhead
766
- // IMPORTANT: Disable ECHO mode to prevent output duplication
767
- sshClient.exec(fullCommand, {
768
- pty: {
769
- term: 'xterm-256color',
770
- cols,
771
- rows,
772
- modes: {
773
- ECHO: 0 // Disable echo to prevent duplicate output
774
- }
775
- }
776
- }, (err, execStream) => {
777
- if (err) {
778
- logError('Failed to execute SSH command', err);
779
- onExit(1);
780
- return;
721
+ function runLocalPty(command, cwd, onData, onExit, initialCols, initialRows) {
722
+ const cols = initialCols || process.stdout.columns || 80;
723
+ const rows = initialRows || process.stdout.rows || 24;
724
+ const shell = getShellCommand();
725
+ const isWindows = os.platform() === "win32";
726
+ const isBash = usesBashArgs(shell);
727
+ const shellArgs = isBash ? ["-c", command] : isWindows ? ["-Command", command] : ["-c", command];
728
+ const ptyProcess = nodePty.spawn(shell, shellArgs, {
729
+ name: isWindows ? "cygwin" : "xterm-256color",
730
+ // cygwin for Windows compatibility
731
+ cols,
732
+ rows,
733
+ cwd,
734
+ env: {
735
+ ...process.env,
736
+ TERM: isWindows ? "cygwin" : "xterm-256color",
737
+ COLORTERM: "truecolor"
738
+ }
739
+ });
740
+ let isRunning = true;
741
+ ptyProcess.onData((data) => {
742
+ if (isRunning) {
743
+ onData(data);
744
+ }
745
+ });
746
+ ptyProcess.onExit(({ exitCode }) => {
747
+ isRunning = false;
748
+ onExit(exitCode);
749
+ });
750
+ return {
751
+ write: (data) => {
752
+ if (isRunning) {
753
+ ptyProcess.write(data);
754
+ }
755
+ },
756
+ kill: () => {
757
+ if (isRunning) {
758
+ isRunning = false;
759
+ try {
760
+ ptyProcess.kill();
761
+ } catch (e) {
781
762
  }
782
- stream = execStream;
783
- // Stream output to callback
784
- // Note: In PTY mode, stdout and stderr are merged into a single stream
785
- stream.on('data', (data) => {
786
- if (isRunning) {
787
- onData(data.toString());
788
- }
789
- });
790
- // Handle stream close with exit code
791
- stream.on('close', (code) => {
792
- isRunning = false;
793
- onExit(code || 0);
794
- });
795
- });
796
- return {
797
- write: (data) => {
798
- if (isRunning && stream) {
799
- stream.write(data);
800
- }
801
- },
802
- kill: () => {
803
- if (isRunning) {
804
- isRunning = false;
805
- if (stream) {
806
- try {
807
- stream.close();
808
- }
809
- catch (e) {
810
- // Ignore close errors
811
- }
812
- }
813
- }
814
- },
815
- resize: (cols, rows) => {
816
- if (isRunning && stream) {
817
- try {
818
- stream.setWindow(rows, cols, 0, 0);
819
- }
820
- catch (e) {
821
- // Ignore resize errors
822
- }
823
- }
824
- },
825
- isRunning: () => isRunning
826
- };
827
- }
828
- /**
829
- * Run a command in a local PTY.
830
- * Useful for executing commands that are either local or wrapped (e.g., `wsl ...` or `ssh ...`).
831
- */
832
- export function runLocalPty(command, cwd, onData, onExit, initialCols, initialRows) {
833
- // Get terminal dimensions - use provided values or fall back to process.stdout
834
- const cols = initialCols || process.stdout.columns || 80;
835
- const rows = initialRows || process.stdout.rows || 24;
836
- const shell = getShellCommand();
837
- const isWindows = os.platform() === 'win32';
838
- // Use bash-style args for Git Bash
839
- const isBash = usesBashArgs(shell);
840
- const shellArgs = isBash ? ['-c', command] : (isWindows ? ['-Command', command] : ['-c', command]);
841
- // Spawn PTY process
842
- const ptyProcess = nodePty.spawn(shell, shellArgs, {
843
- name: isWindows ? 'cygwin' : 'xterm-256color', // cygwin for Windows compatibility
844
- cols,
845
- rows,
846
- cwd,
847
- env: {
848
- ...process.env,
849
- TERM: isWindows ? 'cygwin' : 'xterm-256color',
850
- COLORTERM: 'truecolor',
851
- },
852
- });
853
- let isRunning = true;
854
- // Stream output to callback
855
- ptyProcess.onData((data) => {
856
- if (isRunning) {
857
- onData(data);
763
+ }
764
+ },
765
+ resize: (cols2, rows2) => {
766
+ if (isRunning) {
767
+ try {
768
+ ptyProcess.resize(cols2, rows2);
769
+ } catch (e) {
858
770
  }
859
- });
860
- // Handle exit
861
- ptyProcess.onExit(({ exitCode }) => {
862
- isRunning = false;
863
- onExit(exitCode);
864
- });
865
- return {
866
- write: (data) => {
867
- if (isRunning) {
868
- ptyProcess.write(data);
869
- }
870
- },
871
- kill: () => {
872
- if (isRunning) {
873
- isRunning = false;
874
- try {
875
- ptyProcess.kill();
876
- }
877
- catch (e) {
878
- // Ignore kill errors
879
- }
880
- }
881
- },
882
- resize: (cols, rows) => {
883
- if (isRunning) {
884
- try {
885
- ptyProcess.resize(cols, rows);
886
- }
887
- catch (e) {
888
- // Ignore resize errors
889
- }
890
- }
891
- },
892
- isRunning: () => isRunning
893
- };
771
+ }
772
+ },
773
+ isRunning: () => isRunning
774
+ };
894
775
  }
776
+ export {
777
+ getEditorName,
778
+ isInteractiveEditorCommand,
779
+ isNanoEditor,
780
+ runDockerCommand,
781
+ runDockerEditor,
782
+ runInteractiveEditor,
783
+ runLocalPty,
784
+ runNestedDockerSSHEditor,
785
+ runSSHCommand,
786
+ runSSHEditor,
787
+ runWSLCommand,
788
+ runWSLEditor
789
+ };
895
790
  //# sourceMappingURL=editor-utils.js.map