centaurus-cli 3.0.1 → 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 -5158
  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 +1526 -1512
  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 +601 -572
  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 -406
  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 -3263
  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 -514
  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 -204
  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,649 +1,577 @@
1
- /**
2
- * WSL Handler for Windows Subsystem for Linux
3
- */
4
- import { exec, spawn } from 'child_process';
5
- import { promisify } from 'util';
6
- import { SubshellConnectionError, SubshellExecutionError } from '../types.js';
7
- import { randomBytes } from 'crypto';
8
- import * as os from 'os';
1
+ import { exec, spawn } from "child_process";
2
+ import { promisify } from "util";
3
+ import { SubshellConnectionError, SubshellExecutionError } from "../types.js";
4
+ import { randomBytes } from "crypto";
5
+ import * as os from "os";
9
6
  const execAsync = promisify(exec);
10
- /**
11
- * WSL Handler implementation
12
- */
13
- export class WSLHandler {
14
- type = 'wsl';
15
- detectionPatterns = [
16
- /^wsl$/,
17
- /^wsl\s+/,
18
- /^wsl\.exe\s+/,
19
- ];
20
- config = null;
21
- currentWorkingDirectory = '~';
22
- shellType = 'bash';
23
- sessionId = '';
24
- shellProcess = null;
25
- commandQueue = [];
26
- currentOutput = '';
27
- currentError = '';
28
- // Streaming output callback for real-time display
29
- onOutputCallback = null;
30
- /**
31
- * Set a callback to receive real-time output from commands
32
- * This is essential for interactive commands like sudo that need user input
33
- */
34
- setOutputCallback(callback) {
35
- this.onOutputCallback = callback;
36
- }
37
- /**
38
- * Write data to the shell's stdin (for user input like passwords)
39
- */
40
- writeToStdin(data) {
41
- if (this.shellProcess && this.shellProcess.stdin && !this.shellProcess.stdin.destroyed) {
42
- this.shellProcess.stdin.write(data);
43
- return true;
44
- }
45
- return false;
46
- }
47
- /**
48
- * Detect if a command should trigger this handler
49
- */
50
- detect(command) {
51
- return this.detectionPatterns.some(pattern => pattern.test(command));
52
- }
53
- /**
54
- * Connect to the WSL environment
55
- */
56
- async connect(command, cwd) {
57
- this.sessionId = randomBytes(16).toString('hex');
58
- try {
59
- // Verify WSL is available (Windows only)
60
- this.verifyWSLAvailable();
61
- // Parse WSL command to extract distribution
62
- this.config = await this.parseWSLCommand(command);
63
- // Spawn interactive shell
64
- await this.spawnInteractiveShell();
65
- // Detect shell type
66
- this.shellType = await this.detectShellType();
67
- // Get initial working directory
68
- this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
69
- return {
70
- type: 'wsl',
71
- handler: this,
72
- metadata: {
73
- workingDirectory: this.currentWorkingDirectory,
74
- shell: this.shellType,
75
- os: 'linux',
76
- distroName: this.config.distribution,
77
- },
78
- connectionState: 'connected',
79
- sessionId: this.sessionId,
80
- };
81
- }
82
- catch (error) {
83
- throw new SubshellConnectionError('wsl', error instanceof Error ? error.message : 'Unknown error', false);
84
- }
7
+ class WSLHandler {
8
+ type = "wsl";
9
+ detectionPatterns = [
10
+ /^wsl$/,
11
+ /^wsl\s+/,
12
+ /^wsl\.exe\s+/
13
+ ];
14
+ config = null;
15
+ currentWorkingDirectory = "~";
16
+ shellType = "bash";
17
+ sessionId = "";
18
+ shellProcess = null;
19
+ commandQueue = [];
20
+ currentOutput = "";
21
+ currentError = "";
22
+ // Streaming output callback for real-time display
23
+ onOutputCallback = null;
24
+ /**
25
+ * Set a callback to receive real-time output from commands
26
+ * This is essential for interactive commands like sudo that need user input
27
+ */
28
+ setOutputCallback(callback) {
29
+ this.onOutputCallback = callback;
30
+ }
31
+ /**
32
+ * Write data to the shell's stdin (for user input like passwords)
33
+ */
34
+ writeToStdin(data) {
35
+ if (this.shellProcess && this.shellProcess.stdin && !this.shellProcess.stdin.destroyed) {
36
+ this.shellProcess.stdin.write(data);
37
+ return true;
85
38
  }
86
- /**
87
- * Spawn an interactive shell process
88
- */
89
- async spawnInteractiveShell() {
90
- if (!this.config) {
91
- throw new Error('Config not initialized');
92
- }
93
- const distro = this.config.distribution.trim().replace(/\0/g, '');
94
- return new Promise((resolve, reject) => {
95
- // Spawn wsl.exe with the distribution
96
- this.shellProcess = spawn('wsl.exe', ['-d', distro], {
97
- stdio: ['pipe', 'pipe', 'pipe'],
98
- shell: false,
99
- });
100
- if (!this.shellProcess.stdout || !this.shellProcess.stderr || !this.shellProcess.stdin) {
101
- reject(new Error('Failed to create shell process streams'));
102
- return;
103
- }
104
- let hasResolved = false;
105
- let errorOutput = '';
106
- let initCommandSent = false;
107
- // Set up output handlers
108
- this.shellProcess.stdout.on('data', (data) => {
109
- const text = data.toString();
110
- this.currentOutput += text;
111
- // Stream to callback if registered (for real-time UI display)
112
- if (this.onOutputCallback) {
113
- this.onOutputCallback(text, 'stdout');
114
- }
115
- // If we get any output, the shell is working
116
- if (!hasResolved) {
117
- hasResolved = true;
118
- resolve();
119
- }
120
- });
121
- this.shellProcess.stderr.on('data', (data) => {
122
- const text = data.toString();
123
- this.currentError += text;
124
- errorOutput += text;
125
- // Stream to callback if registered (for real-time UI display)
126
- if (this.onOutputCallback) {
127
- this.onOutputCallback(text, 'stderr');
128
- }
129
- });
130
- this.shellProcess.on('exit', (code) => {
131
- if (!hasResolved) {
132
- hasResolved = true;
133
- // Check for common WSL errors
134
- if (errorOutput.includes('HCS_E_SERVICE_NOT_AVAILABLE')) {
135
- reject(new Error('WSL service is not running. Try running "wsl --shutdown" and then try again, or restart your computer.'));
136
- }
137
- else if (errorOutput.includes('required feature is not installed')) {
138
- reject(new Error('WSL is not properly installed or enabled. Please ensure WSL 2 is installed and the Virtual Machine Platform feature is enabled.'));
139
- }
140
- else {
141
- reject(new Error(`WSL process exited with code ${code}. Error: ${errorOutput || 'No error output'}`));
142
- }
143
- }
144
- this.shellProcess = null;
145
- });
146
- this.shellProcess.on('error', (error) => {
147
- if (!hasResolved) {
148
- hasResolved = true;
149
- reject(new Error(`Failed to spawn WSL process: ${error.message}`));
150
- }
151
- });
152
- // Wait for stdin to be ready, then send initialization command
153
- const sendInitCommand = () => {
154
- if (!initCommandSent && this.shellProcess && this.shellProcess.stdin && !this.shellProcess.stdin.destroyed) {
155
- initCommandSent = true;
156
- this.shellProcess.stdin.write('echo "CENTAURUS_READY"\n');
157
- }
158
- };
159
- // Try to send command immediately if stdin is already writable
160
- if (this.shellProcess.stdin.writable) {
161
- sendInitCommand();
162
- }
163
- else {
164
- // Otherwise wait for the 'ready' event on stdin
165
- this.shellProcess.stdin.once('ready', sendInitCommand);
166
- }
167
- // Fallback: also try after a small delay in case ready event doesn't fire
168
- setTimeout(() => {
169
- sendInitCommand();
170
- }, 200);
171
- // Timeout if we don't get a response
172
- // WSL cold-start can take 10+ seconds on first run
173
- setTimeout(() => {
174
- if (!hasResolved) {
175
- hasResolved = true;
176
- reject(new Error(`WSL shell initialization timed out. Error: ${errorOutput || 'No error output'}`));
177
- }
178
- }, 15000);
179
- });
39
+ return false;
40
+ }
41
+ /**
42
+ * Detect if a command should trigger this handler
43
+ */
44
+ detect(command) {
45
+ return this.detectionPatterns.some((pattern) => pattern.test(command));
46
+ }
47
+ /**
48
+ * Connect to the WSL environment
49
+ */
50
+ async connect(command, cwd) {
51
+ this.sessionId = randomBytes(16).toString("hex");
52
+ try {
53
+ this.verifyWSLAvailable();
54
+ this.config = await this.parseWSLCommand(command);
55
+ await this.spawnInteractiveShell();
56
+ this.shellType = await this.detectShellType();
57
+ this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
58
+ return {
59
+ type: "wsl",
60
+ handler: this,
61
+ metadata: {
62
+ workingDirectory: this.currentWorkingDirectory,
63
+ shell: this.shellType,
64
+ os: "linux",
65
+ distroName: this.config.distribution
66
+ },
67
+ connectionState: "connected",
68
+ sessionId: this.sessionId
69
+ };
70
+ } catch (error) {
71
+ throw new SubshellConnectionError(
72
+ "wsl",
73
+ error instanceof Error ? error.message : "Unknown error",
74
+ false
75
+ );
180
76
  }
181
- /**
182
- * Disconnect from the WSL environment
183
- */
184
- async disconnect() {
185
- if (this.shellProcess) {
186
- this.shellProcess.kill();
187
- this.shellProcess = null;
188
- }
189
- this.config = null;
190
- }
191
- /**
192
- * Check if this handler is currently connected to a WSL environment
193
- */
194
- isConnected() {
195
- return this.config !== null && this.shellProcess !== null;
196
- }
197
- /**
198
- * Execute a command in the WSL environment
199
- */
200
- async executeCommand(command) {
201
- if (!this.config) {
202
- throw new SubshellExecutionError(command, 'Not connected to WSL - config is null');
203
- }
204
- if (!this.shellProcess) {
205
- throw new SubshellExecutionError(command, 'Not connected to WSL - shell process is null');
206
- }
207
- if (!this.shellProcess.stdin) {
208
- throw new SubshellExecutionError(command, 'Not connected to WSL - stdin is null');
209
- }
210
- if (this.shellProcess.killed || this.shellProcess.exitCode !== null) {
211
- throw new SubshellExecutionError(command, 'Not connected to WSL - shell process has exited');
212
- }
213
- try {
214
- // Clear previous output
215
- this.currentOutput = '';
216
- this.currentError = '';
217
- // Unique PWD tag for this session
218
- const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
219
- // Build command with pwd tracking
220
- let commandWithPwd;
221
- const trimmedCommand = command.trim();
222
- // Check if this is a cd command
223
- if (trimmedCommand.startsWith('cd ') || trimmedCommand === 'cd') {
224
- // For cd commands, execute directly without prepending current directory
225
- // The shell maintains its own state
226
- commandWithPwd = `${command}; echo "${pwdTag}:$(pwd)"\n`;
227
- }
228
- else {
229
- // For other commands, ensure we're in the right directory first
230
- commandWithPwd = `cd ${this.currentWorkingDirectory} && ${command}; echo "${pwdTag}:$(pwd)"\n`;
231
- }
232
- // Send command to shell
233
- this.shellProcess.stdin.write(commandWithPwd);
234
- // Wait for command to complete (look for the pwd marker)
235
- const result = await this.waitForCommandCompletion(30000);
236
- return result;
77
+ }
78
+ /**
79
+ * Spawn an interactive shell process
80
+ */
81
+ async spawnInteractiveShell() {
82
+ if (!this.config) {
83
+ throw new Error("Config not initialized");
84
+ }
85
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
86
+ return new Promise((resolve, reject) => {
87
+ this.shellProcess = spawn("wsl.exe", ["-d", distro], {
88
+ stdio: ["pipe", "pipe", "pipe"],
89
+ shell: false
90
+ });
91
+ if (!this.shellProcess.stdout || !this.shellProcess.stderr || !this.shellProcess.stdin) {
92
+ reject(new Error("Failed to create shell process streams"));
93
+ return;
94
+ }
95
+ let hasResolved = false;
96
+ let errorOutput = "";
97
+ let initCommandSent = false;
98
+ this.shellProcess.stdout.on("data", (data) => {
99
+ const text = data.toString();
100
+ this.currentOutput += text;
101
+ if (this.onOutputCallback) {
102
+ this.onOutputCallback(text, "stdout");
237
103
  }
238
- catch (error) {
239
- return {
240
- stdout: '',
241
- stderr: error.message || 'Command execution failed',
242
- exitCode: 1,
243
- };
104
+ if (!hasResolved) {
105
+ hasResolved = true;
106
+ resolve();
244
107
  }
108
+ });
109
+ this.shellProcess.stderr.on("data", (data) => {
110
+ const text = data.toString();
111
+ this.currentError += text;
112
+ errorOutput += text;
113
+ if (this.onOutputCallback) {
114
+ this.onOutputCallback(text, "stderr");
115
+ }
116
+ });
117
+ this.shellProcess.on("exit", (code) => {
118
+ if (!hasResolved) {
119
+ hasResolved = true;
120
+ if (errorOutput.includes("HCS_E_SERVICE_NOT_AVAILABLE")) {
121
+ reject(new Error('WSL service is not running. Try running "wsl --shutdown" and then try again, or restart your computer.'));
122
+ } else if (errorOutput.includes("required feature is not installed")) {
123
+ reject(new Error("WSL is not properly installed or enabled. Please ensure WSL 2 is installed and the Virtual Machine Platform feature is enabled."));
124
+ } else {
125
+ reject(new Error(`WSL process exited with code ${code}. Error: ${errorOutput || "No error output"}`));
126
+ }
127
+ }
128
+ this.shellProcess = null;
129
+ });
130
+ this.shellProcess.on("error", (error) => {
131
+ if (!hasResolved) {
132
+ hasResolved = true;
133
+ reject(new Error(`Failed to spawn WSL process: ${error.message}`));
134
+ }
135
+ });
136
+ const sendInitCommand = () => {
137
+ if (!initCommandSent && this.shellProcess && this.shellProcess.stdin && !this.shellProcess.stdin.destroyed) {
138
+ initCommandSent = true;
139
+ this.shellProcess.stdin.write('echo "CENTAURUS_READY"\n');
140
+ }
141
+ };
142
+ if (this.shellProcess.stdin.writable) {
143
+ sendInitCommand();
144
+ } else {
145
+ this.shellProcess.stdin.once("ready", sendInitCommand);
146
+ }
147
+ setTimeout(() => {
148
+ sendInitCommand();
149
+ }, 200);
150
+ setTimeout(() => {
151
+ if (!hasResolved) {
152
+ hasResolved = true;
153
+ reject(new Error(`WSL shell initialization timed out. Error: ${errorOutput || "No error output"}`));
154
+ }
155
+ }, 15e3);
156
+ });
157
+ }
158
+ /**
159
+ * Disconnect from the WSL environment
160
+ */
161
+ async disconnect() {
162
+ if (this.shellProcess) {
163
+ this.shellProcess.kill();
164
+ this.shellProcess = null;
245
165
  }
246
- /**
247
- * Wait for command completion by monitoring output
248
- */
249
- async waitForCommandCompletion(timeoutMs = 30000) {
250
- const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
251
- const pwdRegex = new RegExp(`${pwdTag}:(.+)$`, 'm');
252
- const removeRegex = new RegExp(`${pwdTag}:.+$`, 'm');
253
- return new Promise((resolve, reject) => {
254
- const startTime = Date.now();
255
- const checkInterval = setInterval(() => {
256
- if (timeoutMs > 0 && Date.now() - startTime >= timeoutMs) {
257
- clearInterval(checkInterval);
258
- reject(new Error(`Command execution timed out after ${timeoutMs}ms`));
259
- return;
260
- }
261
- const pwdMatch = this.currentOutput.match(pwdRegex);
262
- if (pwdMatch) {
263
- clearInterval(checkInterval);
264
- // Extract working directory
265
- const newCwd = pwdMatch[1].trim();
266
- this.currentWorkingDirectory = newCwd;
267
- // Clean output
268
- const cleanStdout = this.currentOutput
269
- .replace(removeRegex, '')
270
- .trim();
271
- resolve({
272
- stdout: cleanStdout,
273
- stderr: this.currentError,
274
- exitCode: 0,
275
- });
276
- }
277
- }, 100);
278
- });
166
+ this.config = null;
167
+ }
168
+ /**
169
+ * Check if this handler is currently connected to a WSL environment
170
+ */
171
+ isConnected() {
172
+ return this.config !== null && this.shellProcess !== null;
173
+ }
174
+ /**
175
+ * Execute a command in the WSL environment
176
+ */
177
+ async executeCommand(command) {
178
+ if (!this.config) {
179
+ throw new SubshellExecutionError(command, "Not connected to WSL - config is null");
279
180
  }
280
- /**
281
- * Read a file from the WSL filesystem
282
- */
283
- async readFile(path) {
284
- if (!this.config) {
285
- throw new Error('Not connected to WSL');
286
- }
287
- const distro = this.config.distribution.trim().replace(/\0/g, '');
288
- const wslPath = this.resolveWSLPath(path);
289
- // Use base64 to avoid encoding issues and binary-safe transfer
290
- const command = `wsl.exe -d ${distro} -- bash -c "base64 '${wslPath}' 2>/dev/null || cat '${wslPath}' | base64"`;
291
- try {
292
- const { stdout } = await execAsync(command);
293
- const b64 = stdout.replace(/\s+/g, '');
294
- return Buffer.from(b64, 'base64').toString('utf-8');
295
- }
296
- catch (error) {
297
- throw new Error(`Failed to read file ${path}: ${error.message}`);
298
- }
181
+ if (!this.shellProcess) {
182
+ throw new SubshellExecutionError(command, "Not connected to WSL - shell process is null");
299
183
  }
300
- /**
301
- * Write a file to the WSL filesystem
302
- */
303
- async writeFile(path, content) {
304
- if (!this.config) {
305
- throw new Error('Not connected to WSL');
306
- }
307
- const distro = this.config.distribution.trim().replace(/\0/g, '');
308
- const wslPath = this.resolveWSLPath(path);
309
- // Use base64-encoded, chunked writes to avoid shell arg/command length limits
310
- const inputBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');
311
- const base64Content = inputBuffer.toString('base64');
312
- const CHUNK_SIZE = 32000; // conservative size per command
313
- try {
314
- // Truncate/initialize file
315
- const truncateCmd = `wsl.exe -d ${distro} -- bash -c ": > '${wslPath}'"`;
316
- await execAsync(truncateCmd);
317
- // Write in chunks
318
- for (let i = 0; i < base64Content.length; i += CHUNK_SIZE) {
319
- const chunk = base64Content.slice(i, i + CHUNK_SIZE);
320
- const writeCmd = `wsl.exe -d ${distro} -- bash -c "echo '${chunk}' | base64 -d >> '${wslPath}'"`;
321
- await execAsync(writeCmd);
322
- }
323
- }
324
- catch (error) {
325
- throw new Error(`Failed to write file ${path}: ${error.message}`);
326
- }
184
+ if (!this.shellProcess.stdin) {
185
+ throw new SubshellExecutionError(command, "Not connected to WSL - stdin is null");
327
186
  }
328
- /**
329
- * List directory contents in WSL
330
- */
331
- async listDirectory(path) {
332
- if (!this.config) {
333
- throw new Error('Not connected to WSL');
334
- }
335
- const distro = this.config.distribution.trim().replace(/\0/g, '');
336
- const wslPath = this.resolveWSLPath(path);
337
- const command = `wsl.exe -d ${distro} -- ls -la "${wslPath}"`;
338
- try {
339
- const { stdout } = await execAsync(command);
340
- return this.parseDirectoryListing(stdout);
341
- }
342
- catch (error) {
343
- throw new Error(`Failed to list directory ${path}: ${error.message}`);
344
- }
187
+ if (this.shellProcess.killed || this.shellProcess.exitCode !== null) {
188
+ throw new SubshellExecutionError(command, "Not connected to WSL - shell process has exited");
345
189
  }
346
- /**
347
- * Search for files matching a pattern in WSL
348
- */
349
- async searchFiles(pattern, directory) {
350
- if (!this.config) {
351
- throw new Error('Not connected to WSL');
352
- }
353
- const distro = this.config.distribution.trim().replace(/\0/g, '');
354
- const wslPath = this.resolveWSLPath(directory);
355
- const escapedPattern = pattern.replace(/'/g, "'\\''");
356
- const command = `wsl.exe -d ${distro} -- bash -c "grep -rn '${escapedPattern}' '${wslPath}' 2>/dev/null || true"`;
357
- try {
358
- const { stdout } = await execAsync(command);
359
- return this.parseSearchResults(stdout);
360
- }
361
- catch (error) {
362
- // grep returns non-zero if no matches, which is not an error
363
- return [];
364
- }
190
+ try {
191
+ this.currentOutput = "";
192
+ this.currentError = "";
193
+ const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
194
+ let commandWithPwd;
195
+ const trimmedCommand = command.trim();
196
+ if (trimmedCommand.startsWith("cd ") || trimmedCommand === "cd") {
197
+ commandWithPwd = `${command}; echo "${pwdTag}:$(pwd)"
198
+ `;
199
+ } else {
200
+ commandWithPwd = `cd ${this.currentWorkingDirectory} && ${command}; echo "${pwdTag}:$(pwd)"
201
+ `;
202
+ }
203
+ this.shellProcess.stdin.write(commandWithPwd);
204
+ const result = await this.waitForCommandCompletion(3e4);
205
+ return result;
206
+ } catch (error) {
207
+ return {
208
+ stdout: "",
209
+ stderr: error.message || "Command execution failed",
210
+ exitCode: 1
211
+ };
365
212
  }
366
- /**
367
- * Get the current working directory in WSL
368
- */
369
- async getCurrentWorkingDirectory() {
370
- if (!this.config || !this.shellProcess || !this.shellProcess.stdin) {
371
- return '~';
372
- }
373
- try {
374
- // Clear output
375
- this.currentOutput = '';
376
- // Send pwd command
377
- this.shellProcess.stdin.write('pwd\n');
378
- // Wait for output
379
- await new Promise(resolve => setTimeout(resolve, 300));
380
- const lines = this.currentOutput.trim().split('\n');
381
- const path = lines[lines.length - 1].trim();
382
- return path || '~';
383
- }
384
- catch {
385
- return '~';
386
- }
213
+ }
214
+ /**
215
+ * Wait for command completion by monitoring output
216
+ */
217
+ async waitForCommandCompletion(timeoutMs = 3e4) {
218
+ const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
219
+ const pwdRegex = new RegExp(`${pwdTag}:(.+)$`, "m");
220
+ const removeRegex = new RegExp(`${pwdTag}:.+$`, "m");
221
+ return new Promise((resolve, reject) => {
222
+ const startTime = Date.now();
223
+ const checkInterval = setInterval(() => {
224
+ if (timeoutMs > 0 && Date.now() - startTime >= timeoutMs) {
225
+ clearInterval(checkInterval);
226
+ reject(new Error(`Command execution timed out after ${timeoutMs}ms`));
227
+ return;
228
+ }
229
+ const pwdMatch = this.currentOutput.match(pwdRegex);
230
+ if (pwdMatch) {
231
+ clearInterval(checkInterval);
232
+ const newCwd = pwdMatch[1].trim();
233
+ this.currentWorkingDirectory = newCwd;
234
+ const cleanStdout = this.currentOutput.replace(removeRegex, "").trim();
235
+ resolve({
236
+ stdout: cleanStdout,
237
+ stderr: this.currentError,
238
+ exitCode: 0
239
+ });
240
+ }
241
+ }, 100);
242
+ });
243
+ }
244
+ /**
245
+ * Read a file from the WSL filesystem
246
+ */
247
+ async readFile(path) {
248
+ if (!this.config) {
249
+ throw new Error("Not connected to WSL");
387
250
  }
388
- /**
389
- * Get the shell type
390
- */
391
- async getShellType() {
392
- return this.shellType;
393
- }
394
- /**
395
- * Get the operating system type (always linux for WSL)
396
- */
397
- async getOSType() {
398
- return 'linux';
399
- }
400
- /**
401
- * Get breadcrumb information for the UI
402
- */
403
- getBreadcrumbs() {
404
- if (!this.config) {
405
- return [];
406
- }
407
- return [
408
- {
409
- label: 'wsl',
410
- color: 'yellow',
411
- },
412
- {
413
- label: this.config.distribution,
414
- color: 'yellow',
415
- },
416
- ];
417
- }
418
- // Private helper methods
419
- /**
420
- * Verify that WSL is available on the system
421
- */
422
- verifyWSLAvailable() {
423
- if (os.platform() !== 'win32') {
424
- throw new Error('WSL is only available on Windows');
425
- }
251
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
252
+ const wslPath = this.resolveWSLPath(path);
253
+ const command = `wsl.exe -d ${distro} -- bash -c "base64 '${wslPath}' 2>/dev/null || cat '${wslPath}' | base64"`;
254
+ try {
255
+ const { stdout } = await execAsync(command);
256
+ const b64 = stdout.replace(/\s+/g, "");
257
+ return Buffer.from(b64, "base64").toString("utf-8");
258
+ } catch (error) {
259
+ throw new Error(`Failed to read file ${path}: ${error.message}`);
426
260
  }
427
- /**
428
- * Parse WSL command to extract distribution name
429
- */
430
- async parseWSLCommand(command) {
431
- const parts = command.trim().split(/\s+/);
432
- let distribution = '';
433
- // Look for -d or --distribution flag
434
- for (let i = 1; i < parts.length; i++) {
435
- const part = parts[i];
436
- if ((part === '-d' || part === '--distribution') && i + 1 < parts.length) {
437
- distribution = parts[i + 1];
438
- break;
439
- }
440
- }
441
- // If no distribution specified, get the default
442
- if (!distribution) {
443
- distribution = await this.getDefaultDistribution();
444
- }
445
- return {
446
- distribution,
447
- };
448
- }
449
- /**
450
- * Get the default WSL distribution
451
- */
452
- async getDefaultDistribution() {
453
- try {
454
- const { stdout } = await execAsync('wsl.exe --list --verbose');
455
- // Remove BOM and null bytes from output
456
- const cleanOutput = stdout.replace(/^\uFEFF/, '').replace(/\0/g, '');
457
- const lines = cleanOutput.split('\n');
458
- // Find the line with * (default distribution)
459
- for (const line of lines) {
460
- if (line.includes('*')) {
461
- const match = line.match(/\*\s+(\S+)/);
462
- if (match) {
463
- const distro = match[1].trim().replace(/\0/g, '');
464
- if (distro) {
465
- return distro;
466
- }
467
- }
468
- }
469
- }
470
- // If no default found, return the first distribution
471
- for (const line of lines) {
472
- const match = line.match(/^\s+(\S+)/);
473
- if (match && !match[1].includes('NAME')) {
474
- const distro = match[1].trim().replace(/\0/g, '');
475
- if (distro) {
476
- return distro;
477
- }
478
- }
479
- }
480
- throw new Error('No WSL distributions found');
481
- }
482
- catch (error) {
483
- throw new Error('Failed to detect WSL distribution');
484
- }
261
+ }
262
+ /**
263
+ * Write a file to the WSL filesystem
264
+ */
265
+ async writeFile(path, content) {
266
+ if (!this.config) {
267
+ throw new Error("Not connected to WSL");
485
268
  }
486
- /**
487
- * Detect the shell type in WSL
488
- */
489
- async detectShellType() {
490
- if (!this.config || !this.shellProcess || !this.shellProcess.stdin) {
491
- return 'bash';
492
- }
493
- try {
494
- // Clear output
495
- this.currentOutput = '';
496
- // Send command to detect shell
497
- this.shellProcess.stdin.write('echo $SHELL\n');
498
- // Wait for output
499
- await new Promise(resolve => setTimeout(resolve, 300));
500
- const shellPath = this.currentOutput.trim();
501
- if (shellPath.includes('bash'))
502
- return 'bash';
503
- if (shellPath.includes('zsh'))
504
- return 'zsh';
505
- if (shellPath.includes('fish'))
506
- return 'fish';
507
- return 'bash';
508
- }
509
- catch {
510
- return 'bash';
511
- }
269
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
270
+ const wslPath = this.resolveWSLPath(path);
271
+ const inputBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, "utf8");
272
+ const base64Content = inputBuffer.toString("base64");
273
+ const CHUNK_SIZE = 32e3;
274
+ try {
275
+ const truncateCmd = `wsl.exe -d ${distro} -- bash -c ": > '${wslPath}'"`;
276
+ await execAsync(truncateCmd);
277
+ for (let i = 0; i < base64Content.length; i += CHUNK_SIZE) {
278
+ const chunk = base64Content.slice(i, i + CHUNK_SIZE);
279
+ const writeCmd = `wsl.exe -d ${distro} -- bash -c "echo '${chunk}' | base64 -d >> '${wslPath}'"`;
280
+ await execAsync(writeCmd);
281
+ }
282
+ } catch (error) {
283
+ throw new Error(`Failed to write file ${path}: ${error.message}`);
512
284
  }
513
- /**
514
- * Build a WSL command with working directory context
515
- */
516
- buildWSLCommand(command) {
517
- if (!this.config) {
518
- throw new Error('Not connected to WSL');
519
- }
520
- // Validate distribution name
521
- const distro = this.config.distribution.trim().replace(/\0/g, '');
522
- if (!distro) {
523
- throw new Error('Invalid WSL distribution name');
524
- }
525
- // Determine the directory to cd into
526
- const targetDir = this.currentWorkingDirectory === '~' || this.currentWorkingDirectory === ''
527
- ? '~'
528
- : this.currentWorkingDirectory;
529
- // Unique PWD tag
530
- const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
531
- // Build the command with pwd tracking
532
- // Use single quotes to avoid escaping issues with $
533
- const bashScript = `cd ${targetDir} && ${command}; echo "${pwdTag}:$(pwd)"`;
534
- // Use wsl.exe with bash -c and single quotes
535
- return `wsl.exe -d ${distro} -- bash -c '${bashScript.replace(/'/g, "'\\''")}'`;
536
- }
537
- /**
538
- * Convert Windows path to WSL path
539
- */
540
- static windowsToWSLPath(windowsPath) {
541
- // Convert C:\Users\... to /mnt/c/Users/...
542
- const match = windowsPath.match(/^([A-Za-z]):(\\|\/)/);
543
- if (match) {
544
- const drive = match[1].toLowerCase();
545
- const rest = windowsPath.substring(2).replace(/\\/g, '/');
546
- return `/mnt/${drive}${rest}`;
547
- }
548
- // Already a Unix path
549
- return windowsPath.replace(/\\/g, '/');
550
- }
551
- /**
552
- * Convert WSL path to Windows path
553
- */
554
- static wslToWindowsPath(wslPath) {
555
- // Convert /mnt/c/Users/... to C:\Users\...
556
- const match = wslPath.match(/^\/mnt\/([a-z])(\/.*)?$/);
557
- if (match) {
558
- const drive = match[1].toUpperCase();
559
- const rest = (match[2] || '').replace(/\//g, '\\');
560
- return `${drive}:${rest}`;
561
- }
562
- // Not a /mnt path, return as-is
563
- return wslPath;
564
- }
565
- /**
566
- * Resolve a path to a WSL path
567
- */
568
- resolveWSLPath(path) {
569
- // If it's already an absolute Unix path, use it
570
- if (path.startsWith('/')) {
571
- return path;
572
- }
573
- // If it starts with ~, use it
574
- if (path.startsWith('~')) {
575
- return path;
576
- }
577
- // If it's a Windows path, convert it
578
- if (path.match(/^[A-Za-z]:/)) {
579
- return WSLHandler.windowsToWSLPath(path);
580
- }
581
- // Otherwise, treat as relative to current working directory
582
- return `${this.currentWorkingDirectory}/${path}`;
583
- }
584
- /**
585
- * Parse directory listing output
586
- */
587
- parseDirectoryListing(output) {
588
- const entries = [];
589
- const lines = output.split('\n').filter(line => line.trim());
590
- for (const line of lines) {
591
- // Skip total line and current/parent directory
592
- if (line.startsWith('total') || line.endsWith(' .') || line.endsWith(' ..')) {
593
- continue;
594
- }
595
- // Parse ls -la output: permissions links owner group size date time name
596
- const match = line.match(/^([drwx-]+)\s+\d+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+\S+\s+(.+)$/);
597
- if (match) {
598
- const permissions = match[1];
599
- const size = parseInt(match[2], 10);
600
- const name = match[3];
601
- entries.push({
602
- name,
603
- type: permissions.startsWith('d') ? 'directory' : 'file',
604
- size,
605
- permissions,
606
- });
607
- }
608
- }
609
- return entries;
610
- }
611
- /**
612
- * Parse search results from grep output
613
- */
614
- parseSearchResults(output) {
615
- const results = [];
616
- const lines = output.split('\n').filter(line => line.trim());
617
- for (const line of lines) {
618
- const match = line.match(/^(.+?):(\d+):(.+)$/);
619
- if (match) {
620
- results.push({
621
- file: match[1],
622
- line: parseInt(match[2], 10),
623
- content: match[3],
624
- });
285
+ }
286
+ /**
287
+ * List directory contents in WSL
288
+ */
289
+ async listDirectory(path) {
290
+ if (!this.config) {
291
+ throw new Error("Not connected to WSL");
292
+ }
293
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
294
+ const wslPath = this.resolveWSLPath(path);
295
+ const command = `wsl.exe -d ${distro} -- ls -la "${wslPath}"`;
296
+ try {
297
+ const { stdout } = await execAsync(command);
298
+ return this.parseDirectoryListing(stdout);
299
+ } catch (error) {
300
+ throw new Error(`Failed to list directory ${path}: ${error.message}`);
301
+ }
302
+ }
303
+ /**
304
+ * Search for files matching a pattern in WSL
305
+ */
306
+ async searchFiles(pattern, directory) {
307
+ if (!this.config) {
308
+ throw new Error("Not connected to WSL");
309
+ }
310
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
311
+ const wslPath = this.resolveWSLPath(directory);
312
+ const escapedPattern = pattern.replace(/'/g, "'\\''");
313
+ const command = `wsl.exe -d ${distro} -- bash -c "grep -rn '${escapedPattern}' '${wslPath}' 2>/dev/null || true"`;
314
+ try {
315
+ const { stdout } = await execAsync(command);
316
+ return this.parseSearchResults(stdout);
317
+ } catch (error) {
318
+ return [];
319
+ }
320
+ }
321
+ /**
322
+ * Get the current working directory in WSL
323
+ */
324
+ async getCurrentWorkingDirectory() {
325
+ if (!this.config || !this.shellProcess || !this.shellProcess.stdin) {
326
+ return "~";
327
+ }
328
+ try {
329
+ this.currentOutput = "";
330
+ this.shellProcess.stdin.write("pwd\n");
331
+ await new Promise((resolve) => setTimeout(resolve, 300));
332
+ const lines = this.currentOutput.trim().split("\n");
333
+ const path = lines[lines.length - 1].trim();
334
+ return path || "~";
335
+ } catch {
336
+ return "~";
337
+ }
338
+ }
339
+ /**
340
+ * Get the shell type
341
+ */
342
+ async getShellType() {
343
+ return this.shellType;
344
+ }
345
+ /**
346
+ * Get the operating system type (always linux for WSL)
347
+ */
348
+ async getOSType() {
349
+ return "linux";
350
+ }
351
+ /**
352
+ * Get breadcrumb information for the UI
353
+ */
354
+ getBreadcrumbs() {
355
+ if (!this.config) {
356
+ return [];
357
+ }
358
+ return [
359
+ {
360
+ label: "wsl",
361
+ color: "yellow"
362
+ },
363
+ {
364
+ label: this.config.distribution,
365
+ color: "yellow"
366
+ }
367
+ ];
368
+ }
369
+ // Private helper methods
370
+ /**
371
+ * Verify that WSL is available on the system
372
+ */
373
+ verifyWSLAvailable() {
374
+ if (os.platform() !== "win32") {
375
+ throw new Error("WSL is only available on Windows");
376
+ }
377
+ }
378
+ /**
379
+ * Parse WSL command to extract distribution name
380
+ */
381
+ async parseWSLCommand(command) {
382
+ const parts = command.trim().split(/\s+/);
383
+ let distribution = "";
384
+ for (let i = 1; i < parts.length; i++) {
385
+ const part = parts[i];
386
+ if ((part === "-d" || part === "--distribution") && i + 1 < parts.length) {
387
+ distribution = parts[i + 1];
388
+ break;
389
+ }
390
+ }
391
+ if (!distribution) {
392
+ distribution = await this.getDefaultDistribution();
393
+ }
394
+ return {
395
+ distribution
396
+ };
397
+ }
398
+ /**
399
+ * Get the default WSL distribution
400
+ */
401
+ async getDefaultDistribution() {
402
+ try {
403
+ const { stdout } = await execAsync("wsl.exe --list --verbose");
404
+ const cleanOutput = stdout.replace(/^\uFEFF/, "").replace(/\0/g, "");
405
+ const lines = cleanOutput.split("\n");
406
+ for (const line of lines) {
407
+ if (line.includes("*")) {
408
+ const match = line.match(/\*\s+(\S+)/);
409
+ if (match) {
410
+ const distro = match[1].trim().replace(/\0/g, "");
411
+ if (distro) {
412
+ return distro;
625
413
  }
626
- }
627
- return results;
628
- }
629
- /**
630
- * Execute a promise with a timeout
631
- */
632
- async executeWithTimeout(operation, timeoutMs, operationName) {
633
- return Promise.race([
634
- operation(),
635
- new Promise((_, reject) => setTimeout(() => reject(new Error(`${operationName} timed out after ${timeoutMs}ms`)), timeoutMs)),
636
- ]);
637
- }
638
- /**
639
- * Create a new instance of this handler
640
- */
641
- createNew() {
642
- const newHandler = new WSLHandler();
643
- if (this.onOutputCallback) {
644
- newHandler.setOutputCallback(this.onOutputCallback);
645
- }
646
- return newHandler;
414
+ }
415
+ }
416
+ }
417
+ for (const line of lines) {
418
+ const match = line.match(/^\s+(\S+)/);
419
+ if (match && !match[1].includes("NAME")) {
420
+ const distro = match[1].trim().replace(/\0/g, "");
421
+ if (distro) {
422
+ return distro;
423
+ }
424
+ }
425
+ }
426
+ throw new Error("No WSL distributions found");
427
+ } catch (error) {
428
+ throw new Error("Failed to detect WSL distribution");
429
+ }
430
+ }
431
+ /**
432
+ * Detect the shell type in WSL
433
+ */
434
+ async detectShellType() {
435
+ if (!this.config || !this.shellProcess || !this.shellProcess.stdin) {
436
+ return "bash";
437
+ }
438
+ try {
439
+ this.currentOutput = "";
440
+ this.shellProcess.stdin.write("echo $SHELL\n");
441
+ await new Promise((resolve) => setTimeout(resolve, 300));
442
+ const shellPath = this.currentOutput.trim();
443
+ if (shellPath.includes("bash")) return "bash";
444
+ if (shellPath.includes("zsh")) return "zsh";
445
+ if (shellPath.includes("fish")) return "fish";
446
+ return "bash";
447
+ } catch {
448
+ return "bash";
449
+ }
450
+ }
451
+ /**
452
+ * Build a WSL command with working directory context
453
+ */
454
+ buildWSLCommand(command) {
455
+ if (!this.config) {
456
+ throw new Error("Not connected to WSL");
457
+ }
458
+ const distro = this.config.distribution.trim().replace(/\0/g, "");
459
+ if (!distro) {
460
+ throw new Error("Invalid WSL distribution name");
461
+ }
462
+ const targetDir = this.currentWorkingDirectory === "~" || this.currentWorkingDirectory === "" ? "~" : this.currentWorkingDirectory;
463
+ const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
464
+ const bashScript = `cd ${targetDir} && ${command}; echo "${pwdTag}:$(pwd)"`;
465
+ return `wsl.exe -d ${distro} -- bash -c '${bashScript.replace(/'/g, "'\\''")}'`;
466
+ }
467
+ /**
468
+ * Convert Windows path to WSL path
469
+ */
470
+ static windowsToWSLPath(windowsPath) {
471
+ const match = windowsPath.match(/^([A-Za-z]):(\\|\/)/);
472
+ if (match) {
473
+ const drive = match[1].toLowerCase();
474
+ const rest = windowsPath.substring(2).replace(/\\/g, "/");
475
+ return `/mnt/${drive}${rest}`;
476
+ }
477
+ return windowsPath.replace(/\\/g, "/");
478
+ }
479
+ /**
480
+ * Convert WSL path to Windows path
481
+ */
482
+ static wslToWindowsPath(wslPath) {
483
+ const match = wslPath.match(/^\/mnt\/([a-z])(\/.*)?$/);
484
+ if (match) {
485
+ const drive = match[1].toUpperCase();
486
+ const rest = (match[2] || "").replace(/\//g, "\\");
487
+ return `${drive}:${rest}`;
488
+ }
489
+ return wslPath;
490
+ }
491
+ /**
492
+ * Resolve a path to a WSL path
493
+ */
494
+ resolveWSLPath(path) {
495
+ if (path.startsWith("/")) {
496
+ return path;
497
+ }
498
+ if (path.startsWith("~")) {
499
+ return path;
500
+ }
501
+ if (path.match(/^[A-Za-z]:/)) {
502
+ return WSLHandler.windowsToWSLPath(path);
503
+ }
504
+ return `${this.currentWorkingDirectory}/${path}`;
505
+ }
506
+ /**
507
+ * Parse directory listing output
508
+ */
509
+ parseDirectoryListing(output) {
510
+ const entries = [];
511
+ const lines = output.split("\n").filter((line) => line.trim());
512
+ for (const line of lines) {
513
+ if (line.startsWith("total") || line.endsWith(" .") || line.endsWith(" ..")) {
514
+ continue;
515
+ }
516
+ const match = line.match(/^([drwx-]+)\s+\d+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+\S+\s+(.+)$/);
517
+ if (match) {
518
+ const permissions = match[1];
519
+ const size = parseInt(match[2], 10);
520
+ const name = match[3];
521
+ entries.push({
522
+ name,
523
+ type: permissions.startsWith("d") ? "directory" : "file",
524
+ size,
525
+ permissions
526
+ });
527
+ }
528
+ }
529
+ return entries;
530
+ }
531
+ /**
532
+ * Parse search results from grep output
533
+ */
534
+ parseSearchResults(output) {
535
+ const results = [];
536
+ const lines = output.split("\n").filter((line) => line.trim());
537
+ for (const line of lines) {
538
+ const match = line.match(/^(.+?):(\d+):(.+)$/);
539
+ if (match) {
540
+ results.push({
541
+ file: match[1],
542
+ line: parseInt(match[2], 10),
543
+ content: match[3]
544
+ });
545
+ }
546
+ }
547
+ return results;
548
+ }
549
+ /**
550
+ * Execute a promise with a timeout
551
+ */
552
+ async executeWithTimeout(operation, timeoutMs, operationName) {
553
+ return Promise.race([
554
+ operation(),
555
+ new Promise(
556
+ (_, reject) => setTimeout(
557
+ () => reject(new Error(`${operationName} timed out after ${timeoutMs}ms`)),
558
+ timeoutMs
559
+ )
560
+ )
561
+ ]);
562
+ }
563
+ /**
564
+ * Create a new instance of this handler
565
+ */
566
+ createNew() {
567
+ const newHandler = new WSLHandler();
568
+ if (this.onOutputCallback) {
569
+ newHandler.setOutputCallback(this.onOutputCallback);
647
570
  }
571
+ return newHandler;
572
+ }
648
573
  }
574
+ export {
575
+ WSLHandler
576
+ };
649
577
  //# sourceMappingURL=wsl-handler.js.map