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,607 +1,549 @@
1
- /**
2
- * Docker Handler for container execution
3
- */
4
- import { exec } from 'child_process';
5
- import { promisify } from 'util';
6
- import { writeFile, unlink } from 'fs/promises';
7
- import { tmpdir } from 'os';
8
- import { join } from 'path';
9
- import { SubshellConnectionError, SubshellExecutionError } from '../types.js';
10
- import { randomBytes } from 'crypto';
11
- import { quickLog } from '../../utils/conversation-logger.js';
1
+ import { exec } from "child_process";
2
+ import { promisify } from "util";
3
+ import { writeFile, unlink } from "fs/promises";
4
+ import { tmpdir } from "os";
5
+ import { join } from "path";
6
+ import { SubshellConnectionError, SubshellExecutionError } from "../types.js";
7
+ import { randomBytes } from "crypto";
8
+ import { quickLog } from "../../utils/conversation-logger.js";
12
9
  const execAsync = promisify(exec);
13
- /**
14
- * Docker Handler implementation
15
- */
16
- export class DockerHandler {
17
- type = 'docker';
18
- detectionPatterns = [
19
- /^docker\s+exec\s+/,
20
- /^docker\s+exec\s+-it\s+/,
21
- ];
22
- config = null;
23
- currentWorkingDirectory = '/';
24
- shellType = 'sh';
25
- osType = 'linux';
26
- sessionId = '';
27
- parentContext; // For nested connections
28
- /**
29
- * Detect if a command should trigger this handler
30
- */
31
- detect(command) {
32
- return this.detectionPatterns.some(pattern => pattern.test(command));
10
+ class DockerHandler {
11
+ type = "docker";
12
+ detectionPatterns = [
13
+ /^docker\s+exec\s+/,
14
+ /^docker\s+exec\s+-it\s+/
15
+ ];
16
+ config = null;
17
+ currentWorkingDirectory = "/";
18
+ shellType = "sh";
19
+ osType = "linux";
20
+ sessionId = "";
21
+ parentContext;
22
+ // For nested connections
23
+ /**
24
+ * Detect if a command should trigger this handler
25
+ */
26
+ detect(command) {
27
+ return this.detectionPatterns.some((pattern) => pattern.test(command));
28
+ }
29
+ /**
30
+ * Connect to the Docker container
31
+ */
32
+ async connect(command, cwd) {
33
+ this.sessionId = randomBytes(16).toString("hex");
34
+ try {
35
+ this.config = this.parseDockerCommand(command);
36
+ await this.verifyContainer();
37
+ this.shellType = await this.detectShellType();
38
+ this.osType = await this.detectOSType();
39
+ this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
40
+ return {
41
+ type: "docker",
42
+ handler: this,
43
+ metadata: {
44
+ workingDirectory: this.currentWorkingDirectory,
45
+ shell: this.shellType,
46
+ os: this.osType,
47
+ containerId: this.config.containerId
48
+ },
49
+ connectionState: "connected",
50
+ sessionId: this.sessionId
51
+ };
52
+ } catch (error) {
53
+ throw new SubshellConnectionError(
54
+ "docker",
55
+ error instanceof Error ? error.message : "Unknown error",
56
+ false
57
+ );
33
58
  }
34
- /**
35
- * Connect to the Docker container
36
- */
37
- async connect(command, cwd) {
38
- this.sessionId = randomBytes(16).toString('hex');
59
+ }
60
+ /**
61
+ * Connect from an existing remote context (nested session)
62
+ */
63
+ async connectFromRemote(command, cwd, parentContext) {
64
+ this.sessionId = randomBytes(16).toString("hex");
65
+ this.parentContext = parentContext;
66
+ try {
67
+ this.config = this.parseDockerCommand(command);
68
+ try {
69
+ await this.verifyContainer();
70
+ const result = await this.executeCommand("echo verification");
71
+ if (result.exitCode !== 0 || result.stderr && (result.stderr.includes("npipe:") || result.stderr.includes("pipe/docker"))) {
72
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Remote Docker execution failed, attempting local fallback. Error: ${result.stderr || "exit code " + result.exitCode}
73
+ `);
74
+ throw new Error(`Docker execution failed remotely: ${result.stderr || "exit code " + result.exitCode}`);
75
+ }
76
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Successfully verified Docker execution via remote context
77
+ `);
78
+ } catch (remoteError) {
79
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Attempting local fallback for Docker execution
80
+ `);
81
+ const originalParent = this.parentContext;
82
+ this.parentContext = void 0;
39
83
  try {
40
- // Parse Docker command to extract container ID
41
- this.config = this.parseDockerCommand(command);
42
- // Verify container exists and is running
43
- await this.verifyContainer();
44
- // Detect shell type and OS
45
- this.shellType = await this.detectShellType();
46
- this.osType = await this.detectOSType();
47
- // Get initial working directory
48
- this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
49
- return {
50
- type: 'docker',
51
- handler: this,
52
- metadata: {
53
- workingDirectory: this.currentWorkingDirectory,
54
- shell: this.shellType,
55
- os: this.osType,
56
- containerId: this.config.containerId,
57
- },
58
- connectionState: 'connected',
59
- sessionId: this.sessionId,
60
- };
61
- }
62
- catch (error) {
63
- throw new SubshellConnectionError('docker', error instanceof Error ? error.message : 'Unknown error', false);
64
- }
84
+ await this.verifyContainer();
85
+ const localResult = await this.executeCommand("echo verification");
86
+ if (localResult.exitCode !== 0 || localResult.stderr && (localResult.stderr.includes("npipe:") || localResult.stderr.includes("pipe/docker"))) {
87
+ throw new Error(`Local Docker execution also failed: ${localResult.stderr || "exit code " + localResult.exitCode}`);
88
+ }
89
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Successfully fell back to local Docker execution (parentContext cleared)
90
+ `);
91
+ } catch (localError) {
92
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Local fallback also failed, restoring remote context
93
+ `);
94
+ this.parentContext = originalParent;
95
+ throw remoteError;
96
+ }
97
+ }
98
+ this.shellType = await this.detectShellType();
99
+ this.osType = await this.detectOSType();
100
+ this.currentWorkingDirectory = "";
101
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] Reset currentWorkingDirectory, calling getCurrentWorkingDirectory()
102
+ `);
103
+ this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
104
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] After getCurrentWorkingDirectory, currentWorkingDirectory=${this.currentWorkingDirectory}
105
+ `);
106
+ return {
107
+ type: "docker",
108
+ handler: this,
109
+ metadata: {
110
+ workingDirectory: this.currentWorkingDirectory,
111
+ shell: this.shellType,
112
+ os: this.osType,
113
+ containerId: this.config.containerId
114
+ },
115
+ connectionState: "connected",
116
+ sessionId: this.sessionId
117
+ };
118
+ } catch (error) {
119
+ this.parentContext = void 0;
120
+ throw new SubshellConnectionError(
121
+ "docker",
122
+ error instanceof Error ? error.message : "Unknown error",
123
+ false
124
+ );
125
+ }
126
+ }
127
+ /**
128
+ * Disconnect from the Docker container
129
+ */
130
+ async disconnect() {
131
+ this.config = null;
132
+ }
133
+ /**
134
+ * Check if this handler is currently connected to a Docker container
135
+ */
136
+ isConnected() {
137
+ return this.config !== null;
138
+ }
139
+ /**
140
+ * Execute a command in the Docker container
141
+ */
142
+ async executeCommand(command) {
143
+ if (!this.config) {
144
+ throw new SubshellExecutionError(command, "Not connected to Docker container");
65
145
  }
66
- /**
67
- * Connect from an existing remote context (nested session)
68
- */
69
- async connectFromRemote(command, cwd, parentContext) {
70
- this.sessionId = randomBytes(16).toString('hex');
71
- this.parentContext = parentContext;
146
+ const isCdCommand = /^\s*cd\s+/.test(command) || command.trim() === "cd";
147
+ const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
148
+ try {
149
+ const oldCwd = this.currentWorkingDirectory || "/";
150
+ const dockerCommand = this.buildDockerCommand(command, pwdTag);
151
+ const { stdout, stderr } = await this.executeWithTimeout(
152
+ () => this.executeHostCommand(dockerCommand),
153
+ 3e4,
154
+ "Command execution"
155
+ );
156
+ const pwdRegex = new RegExp(`${pwdTag}:(.+)$`, "m");
157
+ const pwdMatch = stdout.match(pwdRegex);
158
+ let cleanStdout = stdout;
159
+ if (pwdMatch) {
160
+ const extractedPwd = pwdMatch[1].trim();
161
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] executeCommand extracted CWD from output: "${extractedPwd}"
162
+ `);
163
+ this.currentWorkingDirectory = extractedPwd;
164
+ const removeRegex = new RegExp(`${pwdTag}:.+$`, "m");
165
+ cleanStdout = stdout.replace(removeRegex, "").trim();
166
+ }
167
+ if (isCdCommand) {
72
168
  try {
73
- // Parse Docker command to extract container ID
74
- this.config = this.parseDockerCommand(command);
75
- // Verify container exists AND we can execute commands
76
- // A simple 'docker inspect' might succeed remotely via SSH metadata service,
77
- // but 'docker exec' might fail due to stream/pipe issues (the npipe error).
78
- // We must verify actual execution capability.
79
- try {
80
- await this.verifyContainer();
81
- // Also verify we can actually run a command
82
- const result = await this.executeCommand('echo verification');
83
- // Check if the result indicates Docker pipe errors (exitCode != 0 or stderr contains pipe errors)
84
- if (result.exitCode !== 0 || (result.stderr && (result.stderr.includes('npipe:') || result.stderr.includes('pipe/docker')))) {
85
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Remote Docker execution failed, attempting local fallback. Error: ${result.stderr || 'exit code ' + result.exitCode}\n`);
86
- throw new Error(`Docker execution failed remotely: ${result.stderr || 'exit code ' + result.exitCode}`);
87
- }
88
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Successfully verified Docker execution via remote context\n`);
89
- }
90
- catch (remoteError) {
91
- // Fallback: If remote execution fails, try local execution
92
- // This handles scenarios like SSH-ing to localhost where Docker pipes aren't accessible remotely
93
- // but are accessible locally.
94
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Attempting local fallback for Docker execution\n`);
95
- const originalParent = this.parentContext;
96
- this.parentContext = undefined; // Temporarily switch to local
97
- try {
98
- await this.verifyContainer();
99
- // Also verify we can execute commands locally
100
- const localResult = await this.executeCommand('echo verification');
101
- if (localResult.exitCode !== 0 || (localResult.stderr && (localResult.stderr.includes('npipe:') || localResult.stderr.includes('pipe/docker')))) {
102
- throw new Error(`Local Docker execution also failed: ${localResult.stderr || 'exit code ' + localResult.exitCode}`);
103
- }
104
- // If successful, keep parentContext as undefined (permanent fallback to local)
105
- // Note: We'll get the proper CWD later via getCurrentWorkingDirectory()
106
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Successfully fell back to local Docker execution (parentContext cleared)\n`);
107
- }
108
- catch (localError) {
109
- // If local also fails, restore parent context and throw original remote error
110
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Local fallback also failed, restoring remote context\n`);
111
- this.parentContext = originalParent;
112
- throw remoteError;
113
- }
114
- }
115
- // Detect shell type and OS
116
- this.shellType = await this.detectShellType();
117
- this.osType = await this.detectOSType();
118
- // Get initial working directory - reset first to force fresh detection
119
- // The verification command may have polluted currentWorkingDirectory via __CENTAURUS_PWD__ extraction
120
- // which can have incorrect values due to SSH shell evaluation
121
- this.currentWorkingDirectory = '';
122
- quickLog(`[${new Date().toISOString()}] [DockerHandler] Reset currentWorkingDirectory, calling getCurrentWorkingDirectory()\n`);
123
- this.currentWorkingDirectory = await this.getCurrentWorkingDirectory();
124
- quickLog(`[${new Date().toISOString()}] [DockerHandler] After getCurrentWorkingDirectory, currentWorkingDirectory=${this.currentWorkingDirectory}\n`);
125
- return {
126
- type: 'docker',
127
- handler: this,
128
- metadata: {
129
- workingDirectory: this.currentWorkingDirectory,
130
- shell: this.shellType,
131
- os: this.osType,
132
- containerId: this.config.containerId,
133
- },
134
- connectionState: 'connected',
135
- sessionId: this.sessionId,
136
- };
137
- }
138
- catch (error) {
139
- this.parentContext = undefined; // Reset on failure
140
- throw new SubshellConnectionError('docker', error instanceof Error ? error.message : 'Unknown error', false);
141
- }
169
+ const escapedOldCwd = oldCwd.replace(/"/g, '\\"');
170
+ const escapedCommand = command.replace(/"/g, '\\"');
171
+ const pwdCommand = `docker exec ${this.config.containerId} sh -c "cd \\"${escapedOldCwd}\\" && ${escapedCommand} && pwd"`;
172
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] cd verification command: ${pwdCommand}
173
+ `);
174
+ const { stdout: pwdOutput } = await this.executeHostCommand(pwdCommand);
175
+ const actualCwd = pwdOutput.trim();
176
+ if (actualCwd && actualCwd.startsWith("/")) {
177
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] cd command: verified CWD is "${actualCwd}"
178
+ `);
179
+ this.currentWorkingDirectory = actualCwd;
180
+ }
181
+ } catch (pwdError) {
182
+ quickLog(`[${(/* @__PURE__ */ new Date()).toISOString()}] [DockerHandler] cd command: pwd verification failed, keeping extracted value
183
+ `);
184
+ }
185
+ }
186
+ return {
187
+ stdout: cleanStdout,
188
+ stderr,
189
+ exitCode: 0
190
+ };
191
+ } catch (error) {
192
+ return {
193
+ stdout: "",
194
+ stderr: error.stderr || error.message,
195
+ exitCode: error.code || 1
196
+ };
142
197
  }
143
- /**
144
- * Disconnect from the Docker container
145
- */
146
- async disconnect() {
147
- this.config = null;
198
+ }
199
+ /**
200
+ * Read a file from the Docker container filesystem
201
+ */
202
+ async readFile(path) {
203
+ if (!this.config) {
204
+ throw new Error("Not connected to Docker container");
148
205
  }
149
- /**
150
- * Check if this handler is currently connected to a Docker container
151
- */
152
- isConnected() {
153
- return this.config !== null;
206
+ const absolutePath = this.resolveAbsolutePath(path);
207
+ const command = `docker exec ${this.config.containerId} sh -lc "base64 '${absolutePath}' 2>/dev/null || cat '${absolutePath}' | base64"`;
208
+ try {
209
+ const { stdout } = await this.executeHostCommand(command);
210
+ const b64 = stdout.replace(/\s+/g, "");
211
+ return Buffer.from(b64, "base64").toString("utf-8");
212
+ } catch (error) {
213
+ throw new Error(`Failed to read file ${path}: ${error.message}`);
154
214
  }
155
- /**
156
- * Execute a command in the Docker container
157
- */
158
- async executeCommand(command) {
159
- if (!this.config) {
160
- throw new SubshellExecutionError(command, 'Not connected to Docker container');
161
- }
162
- // Check if this is a cd command - we'll need special CWD handling
163
- const isCdCommand = /^\s*cd\s+/.test(command) || command.trim() === 'cd';
164
- // Use unique PWD tag
165
- const pwdTag = `__CENTAURUS_PWD_${this.sessionId}__`;
166
- try {
167
- // Store old CWD before execution for cd verification
168
- const oldCwd = this.currentWorkingDirectory || '/';
169
- const dockerCommand = this.buildDockerCommand(command, pwdTag);
170
- const { stdout, stderr } = await this.executeWithTimeout(() => this.executeHostCommand(dockerCommand), 30000, 'Command execution');
171
- // Extract working directory from output using unique tag
172
- // We use a constructed regex to match the specific tag for this session
173
- const pwdRegex = new RegExp(`${pwdTag}:(.+)$`, 'm');
174
- const pwdMatch = stdout.match(pwdRegex);
175
- let cleanStdout = stdout;
176
- if (pwdMatch) {
177
- const extractedPwd = pwdMatch[1].trim();
178
- quickLog(`[${new Date().toISOString()}] [DockerHandler] executeCommand extracted CWD from output: "${extractedPwd}"\n`);
179
- this.currentWorkingDirectory = extractedPwd;
180
- // Remove the tag line from stdout
181
- const removeRegex = new RegExp(`${pwdTag}:.+$`, 'm');
182
- cleanStdout = stdout.replace(removeRegex, '').trim();
183
- }
184
- // For cd commands, the $(pwd) extraction through SSH can be unreliable
185
- // due to shell evaluation issues. Run the cd command again with pwd to verify.
186
- if (isCdCommand) {
187
- try {
188
- // Run: cd <old_dir> && <user_cd_command> && pwd to get the actual new directory
189
- const escapedOldCwd = oldCwd.replace(/"/g, '\\"');
190
- const escapedCommand = command.replace(/"/g, '\\"');
191
- // For verification, we don't need the tag since we just want the output
192
- const pwdCommand = `docker exec ${this.config.containerId} sh -c "cd \\"${escapedOldCwd}\\" && ${escapedCommand} && pwd"`;
193
- quickLog(`[${new Date().toISOString()}] [DockerHandler] cd verification command: ${pwdCommand}\n`);
194
- const { stdout: pwdOutput } = await this.executeHostCommand(pwdCommand);
195
- const actualCwd = pwdOutput.trim();
196
- if (actualCwd && actualCwd.startsWith('/')) {
197
- quickLog(`[${new Date().toISOString()}] [DockerHandler] cd command: verified CWD is "${actualCwd}"\n`);
198
- this.currentWorkingDirectory = actualCwd;
199
- }
200
- }
201
- catch (pwdError) {
202
- // If pwd verification fails, keep the extracted value
203
- quickLog(`[${new Date().toISOString()}] [DockerHandler] cd command: pwd verification failed, keeping extracted value\n`);
204
- }
205
- }
206
- return {
207
- stdout: cleanStdout,
208
- stderr,
209
- exitCode: 0,
210
- };
211
- }
212
- catch (error) {
213
- return {
214
- stdout: '',
215
- stderr: error.stderr || error.message,
216
- exitCode: error.code || 1,
217
- };
218
- }
215
+ }
216
+ /**
217
+ * Write a file to the Docker container filesystem
218
+ */
219
+ async writeFile(path, content) {
220
+ if (!this.config) {
221
+ throw new Error("Not connected to Docker container");
219
222
  }
220
- /**
221
- * Read a file from the Docker container filesystem
222
- */
223
- async readFile(path) {
224
- if (!this.config) {
225
- throw new Error('Not connected to Docker container');
226
- }
227
- const absolutePath = this.resolveAbsolutePath(path);
228
- // Use base64 to avoid encoding issues and be binary-safe
229
- const command = `docker exec ${this.config.containerId} sh -lc "base64 '${absolutePath}' 2>/dev/null || cat '${absolutePath}' | base64"`;
223
+ const absolutePath = this.resolveAbsolutePath(path);
224
+ const tempFile = join(tmpdir(), `centaurus-${randomBytes(8).toString("hex")}.tmp`);
225
+ try {
226
+ if (this.parentContext) {
227
+ throw new Error("Remote parent: forcing fallback");
228
+ }
229
+ if (Buffer.isBuffer(content)) {
230
+ await writeFile(tempFile, content);
231
+ } else {
232
+ await writeFile(tempFile, content, "utf8");
233
+ }
234
+ const copyCommand = `docker cp "${tempFile}" ${this.config.containerId}:"${absolutePath}"`;
235
+ await execAsync(copyCommand);
236
+ await unlink(tempFile);
237
+ } catch (error) {
238
+ try {
239
+ await this.executeHostCommand(`docker exec ${this.config.containerId} sh -lc ": > "${absolutePath}""`);
240
+ const inputBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, "utf8");
241
+ const base64Content = inputBuffer.toString("base64");
242
+ const CHUNK_SIZE = 32e3;
243
+ for (let i = 0; i < base64Content.length; i += CHUNK_SIZE) {
244
+ const chunk = base64Content.slice(i, i + CHUNK_SIZE);
245
+ const writeCmd = `docker exec ${this.config.containerId} sh -lc 'echo "${chunk}" | base64 -d >> "${absolutePath}"'`;
246
+ await this.executeHostCommand(writeCmd);
247
+ }
248
+ } catch (fbErr) {
230
249
  try {
231
- const { stdout } = await this.executeHostCommand(command);
232
- const b64 = stdout.replace(/\s+/g, '');
233
- return Buffer.from(b64, 'base64').toString('utf-8');
234
- }
235
- catch (error) {
236
- throw new Error(`Failed to read file ${path}: ${error.message}`);
237
- }
250
+ await unlink(tempFile);
251
+ } catch {
252
+ }
253
+ throw new Error(`Failed to write file ${path}: ${error.message}; fallback failed: ${fbErr.message}`);
254
+ }
255
+ try {
256
+ await unlink(tempFile);
257
+ } catch {
258
+ }
238
259
  }
239
- /**
240
- * Write a file to the Docker container filesystem
241
- */
242
- async writeFile(path, content) {
243
- if (!this.config) {
244
- throw new Error('Not connected to Docker container');
245
- }
246
- const absolutePath = this.resolveAbsolutePath(path);
247
- // Create a temporary file on the host
248
- const tempFile = join(tmpdir(), `centaurus-${randomBytes(8).toString('hex')}.tmp`);
249
- try {
250
- // If remote, skip direct file copy and force fallback
251
- if (this.parentContext) {
252
- throw new Error('Remote parent: forcing fallback');
253
- }
254
- // Write content to temp file
255
- if (Buffer.isBuffer(content)) {
256
- await writeFile(tempFile, content);
257
- }
258
- else {
259
- await writeFile(tempFile, content, 'utf8');
260
- }
261
- // Copy temp file to container
262
- const copyCommand = `docker cp \"${tempFile}\" ${this.config.containerId}:\"${absolutePath}\"`;
263
- await execAsync(copyCommand);
264
- // Clean up temp file
265
- await unlink(tempFile);
266
- }
267
- catch (error) {
268
- // Try base64-over-exec fallback if docker cp fails
269
- try {
270
- // Ensure file is empty first
271
- await this.executeHostCommand(`docker exec ${this.config.containerId} sh -lc ": > \"${absolutePath}\""`);
272
- const inputBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'utf8');
273
- const base64Content = inputBuffer.toString('base64');
274
- const CHUNK_SIZE = 32000;
275
- for (let i = 0; i < base64Content.length; i += CHUNK_SIZE) {
276
- const chunk = base64Content.slice(i, i + CHUNK_SIZE);
277
- const writeCmd = `docker exec ${this.config.containerId} sh -lc 'echo "${chunk}" | base64 -d >> \"${absolutePath}\"'`;
278
- await this.executeHostCommand(writeCmd);
279
- }
280
- }
281
- catch (fbErr) {
282
- // Try to clean up temp file even if fallback also failed
283
- try {
284
- await unlink(tempFile);
285
- }
286
- catch { }
287
- throw new Error(`Failed to write file ${path}: ${error.message}; fallback failed: ${fbErr.message}`);
288
- }
289
- // Try to clean up temp file even if copy failed originally
290
- try {
291
- await unlink(tempFile);
292
- }
293
- catch { }
294
- }
260
+ }
261
+ /**
262
+ * List directory contents in Docker container
263
+ */
264
+ async listDirectory(path) {
265
+ if (!this.config) {
266
+ throw new Error("Not connected to Docker container");
295
267
  }
296
- /**
297
- * List directory contents in Docker container
298
- */
299
- async listDirectory(path) {
300
- if (!this.config) {
301
- throw new Error('Not connected to Docker container');
302
- }
303
- const absolutePath = this.resolveAbsolutePath(path);
304
- const command = `docker exec ${this.config.containerId} ls -la "${absolutePath}"`;
305
- try {
306
- const { stdout } = await this.executeHostCommand(command);
307
- return this.parseDirectoryListing(stdout);
308
- }
309
- catch (error) {
310
- throw new Error(`Failed to list directory ${path}: ${error.message}`);
311
- }
268
+ const absolutePath = this.resolveAbsolutePath(path);
269
+ const command = `docker exec ${this.config.containerId} ls -la "${absolutePath}"`;
270
+ try {
271
+ const { stdout } = await this.executeHostCommand(command);
272
+ return this.parseDirectoryListing(stdout);
273
+ } catch (error) {
274
+ throw new Error(`Failed to list directory ${path}: ${error.message}`);
312
275
  }
313
- /**
314
- * Search for files matching a pattern in Docker container
315
- */
316
- async searchFiles(pattern, directory) {
317
- if (!this.config) {
318
- throw new Error('Not connected to Docker container');
319
- }
320
- const absolutePath = this.resolveAbsolutePath(directory);
321
- const escapedPattern = pattern.replace(/'/g, "'\\''");
322
- const command = `docker exec ${this.config.containerId} sh -c "grep -rn '${escapedPattern}' '${absolutePath}' 2>/dev/null || true"`;
323
- try {
324
- const { stdout } = await this.executeHostCommand(command);
325
- return this.parseSearchResults(stdout);
326
- }
327
- catch (error) {
328
- // grep returns non-zero if no matches, which is not an error
329
- return [];
330
- }
276
+ }
277
+ /**
278
+ * Search for files matching a pattern in Docker container
279
+ */
280
+ async searchFiles(pattern, directory) {
281
+ if (!this.config) {
282
+ throw new Error("Not connected to Docker container");
331
283
  }
332
- /**
333
- * Get the current working directory in the Docker container
334
- * For initial detection: runs pwd in the container
335
- * For subsequent calls: returns the tracked CWD (since each docker exec is a new shell)
336
- */
337
- async getCurrentWorkingDirectory() {
338
- // If we already have a tracked CWD, return it
339
- // This handles the case where cd was used to change directories
340
- if (this.currentWorkingDirectory) {
341
- return this.currentWorkingDirectory;
342
- }
343
- // Initial detection: run pwd to get the container's default working directory
344
- if (!this.config) {
345
- return '/';
346
- }
347
- const command = `docker exec ${this.config.containerId} pwd`;
348
- try {
349
- const { stdout } = await this.executeHostCommand(command);
350
- this.currentWorkingDirectory = stdout.trim() || '/';
351
- return this.currentWorkingDirectory;
352
- }
353
- catch {
354
- return '/';
355
- }
284
+ const absolutePath = this.resolveAbsolutePath(directory);
285
+ const escapedPattern = pattern.replace(/'/g, "'\\''");
286
+ const command = `docker exec ${this.config.containerId} sh -c "grep -rn '${escapedPattern}' '${absolutePath}' 2>/dev/null || true"`;
287
+ try {
288
+ const { stdout } = await this.executeHostCommand(command);
289
+ return this.parseSearchResults(stdout);
290
+ } catch (error) {
291
+ return [];
356
292
  }
357
- /**
358
- * Get the shell type
359
- */
360
- async getShellType() {
361
- return this.shellType;
293
+ }
294
+ /**
295
+ * Get the current working directory in the Docker container
296
+ * For initial detection: runs pwd in the container
297
+ * For subsequent calls: returns the tracked CWD (since each docker exec is a new shell)
298
+ */
299
+ async getCurrentWorkingDirectory() {
300
+ if (this.currentWorkingDirectory) {
301
+ return this.currentWorkingDirectory;
362
302
  }
363
- /**
364
- * Get the operating system type
365
- */
366
- async getOSType() {
367
- return this.osType;
303
+ if (!this.config) {
304
+ return "/";
368
305
  }
369
- /**
370
- * Get breadcrumb information for the UI
371
- */
372
- getBreadcrumbs() {
373
- if (!this.config) {
374
- return [];
375
- }
376
- const displayName = this.config.containerName || this.config.containerId.substring(0, 12);
377
- return [
378
- {
379
- label: 'docker',
380
- color: 'blue',
381
- },
382
- {
383
- label: displayName,
384
- color: 'blue',
385
- },
386
- ];
306
+ const command = `docker exec ${this.config.containerId} pwd`;
307
+ try {
308
+ const { stdout } = await this.executeHostCommand(command);
309
+ this.currentWorkingDirectory = stdout.trim() || "/";
310
+ return this.currentWorkingDirectory;
311
+ } catch {
312
+ return "/";
387
313
  }
388
- // Private helper methods
389
- /**
390
- * Parse Docker exec command to extract container ID
391
- */
392
- parseDockerCommand(command) {
393
- const parts = command.trim().split(/\s+/);
394
- let containerId = '';
395
- // Find the container ID (first non-flag argument after 'exec')
396
- let foundExec = false;
397
- for (let i = 0; i < parts.length; i++) {
398
- const part = parts[i];
399
- if (part === 'exec') {
400
- foundExec = true;
401
- continue;
402
- }
403
- if (foundExec) {
404
- // Skip flags
405
- if (part.startsWith('-')) {
406
- // Check if it's a flag with a value
407
- if (part === '-e' || part === '-w' || part === '-u') {
408
- i++; // Skip the next part (flag value)
409
- }
410
- continue;
411
- }
412
- // This should be the container ID
413
- containerId = part;
414
- break;
415
- }
416
- }
417
- if (!containerId) {
418
- throw new Error('Could not parse container ID from Docker command');
419
- }
420
- return {
421
- containerId,
422
- };
314
+ }
315
+ /**
316
+ * Get the shell type
317
+ */
318
+ async getShellType() {
319
+ return this.shellType;
320
+ }
321
+ /**
322
+ * Get the operating system type
323
+ */
324
+ async getOSType() {
325
+ return this.osType;
326
+ }
327
+ /**
328
+ * Get breadcrumb information for the UI
329
+ */
330
+ getBreadcrumbs() {
331
+ if (!this.config) {
332
+ return [];
423
333
  }
424
- /**
425
- * Verify that the container exists and is running
426
- */
427
- async verifyContainer() {
428
- if (!this.config) {
429
- throw new Error('No container configuration');
430
- }
431
- try {
432
- // Use docker inspect to check container status
433
- const command = `docker inspect --format="{{.State.Running}},{{.Name}}" ${this.config.containerId}`;
434
- const { stdout } = await this.executeHostCommand(command);
435
- const [running, name] = stdout.trim().split(',');
436
- if (running !== 'true') {
437
- throw new Error(`Container ${this.config.containerId} is not running`);
438
- }
439
- // Store container name (remove leading /)
440
- if (name) {
441
- this.config.containerName = name.replace(/^\//, '');
442
- }
443
- }
444
- catch (error) {
445
- if (error.message.includes('No such object')) {
446
- throw new Error(`Container ${this.config.containerId} does not exist`);
447
- }
448
- throw error;
449
- }
334
+ const displayName = this.config.containerName || this.config.containerId.substring(0, 12);
335
+ return [
336
+ {
337
+ label: "docker",
338
+ color: "blue"
339
+ },
340
+ {
341
+ label: displayName,
342
+ color: "blue"
343
+ }
344
+ ];
345
+ }
346
+ // Private helper methods
347
+ /**
348
+ * Parse Docker exec command to extract container ID
349
+ */
350
+ parseDockerCommand(command) {
351
+ const parts = command.trim().split(/\s+/);
352
+ let containerId = "";
353
+ let foundExec = false;
354
+ for (let i = 0; i < parts.length; i++) {
355
+ const part = parts[i];
356
+ if (part === "exec") {
357
+ foundExec = true;
358
+ continue;
359
+ }
360
+ if (foundExec) {
361
+ if (part.startsWith("-")) {
362
+ if (part === "-e" || part === "-w" || part === "-u") {
363
+ i++;
364
+ }
365
+ continue;
366
+ }
367
+ containerId = part;
368
+ break;
369
+ }
450
370
  }
451
- /**
452
- * Detect the shell type in the Docker container
453
- */
454
- async detectShellType() {
455
- if (!this.config) {
456
- return 'sh';
457
- }
458
- try {
459
- // Try to detect shell
460
- const command = `docker exec ${this.config.containerId} sh -c "echo \\$SHELL"`;
461
- const { stdout } = await this.executeHostCommand(command);
462
- const shellPath = stdout.trim();
463
- if (shellPath.includes('bash'))
464
- return 'bash';
465
- if (shellPath.includes('zsh'))
466
- return 'zsh';
467
- if (shellPath.includes('fish'))
468
- return 'fish';
469
- // Default to sh for containers
470
- return 'sh';
471
- }
472
- catch {
473
- return 'sh';
474
- }
371
+ if (!containerId) {
372
+ throw new Error("Could not parse container ID from Docker command");
475
373
  }
476
- /**
477
- * Detect the operating system type in the Docker container
478
- */
479
- async detectOSType() {
480
- if (!this.config) {
481
- return 'linux';
482
- }
483
- try {
484
- const command = `docker exec ${this.config.containerId} uname -s`;
485
- const { stdout } = await this.executeHostCommand(command);
486
- const osName = stdout.trim().toLowerCase();
487
- if (osName.includes('darwin'))
488
- return 'macos';
489
- if (osName.includes('linux'))
490
- return 'linux';
491
- // Most containers are Linux
492
- return 'linux';
493
- }
494
- catch {
495
- return 'linux';
496
- }
374
+ return {
375
+ containerId
376
+ };
377
+ }
378
+ /**
379
+ * Verify that the container exists and is running
380
+ */
381
+ async verifyContainer() {
382
+ if (!this.config) {
383
+ throw new Error("No container configuration");
497
384
  }
498
- /**
499
- * Build a Docker exec command with working directory context
500
- */
501
- buildDockerCommand(command, pwdTag = '__CENTAURUS_PWD__') {
502
- if (!this.config) {
503
- throw new Error('Not connected to Docker container');
504
- }
505
- // Add pwd tracking to command - escape $ so it's evaluated inside Docker, not by SSH shell
506
- const commandWithPwd = `${command}; echo "${pwdTag}:\\$(pwd)"`;
507
- // Use -w flag to set working directory
508
- return `docker exec -w "${this.currentWorkingDirectory}" ${this.config.containerId} sh -c "${commandWithPwd.replace(/"/g, '\\"')}"`;
385
+ try {
386
+ const command = `docker inspect --format="{{.State.Running}},{{.Name}}" ${this.config.containerId}`;
387
+ const { stdout } = await this.executeHostCommand(command);
388
+ const [running, name] = stdout.trim().split(",");
389
+ if (running !== "true") {
390
+ throw new Error(`Container ${this.config.containerId} is not running`);
391
+ }
392
+ if (name) {
393
+ this.config.containerName = name.replace(/^\//, "");
394
+ }
395
+ } catch (error) {
396
+ if (error.message.includes("No such object")) {
397
+ throw new Error(`Container ${this.config.containerId} does not exist`);
398
+ }
399
+ throw error;
509
400
  }
510
- /**
511
- * Resolve a path to an absolute path
512
- */
513
- resolveAbsolutePath(path) {
514
- if (path.startsWith('/')) {
515
- return path;
516
- }
517
- if (path.startsWith('~')) {
518
- return path;
519
- }
520
- return `${this.currentWorkingDirectory}/${path}`;
401
+ }
402
+ /**
403
+ * Detect the shell type in the Docker container
404
+ */
405
+ async detectShellType() {
406
+ if (!this.config) {
407
+ return "sh";
521
408
  }
522
- /**
523
- * Parse directory listing output
524
- */
525
- parseDirectoryListing(output) {
526
- const entries = [];
527
- const lines = output.split('\n').filter(line => line.trim());
528
- for (const line of lines) {
529
- // Skip total line and current/parent directory
530
- if (line.startsWith('total') || line.endsWith(' .') || line.endsWith(' ..')) {
531
- continue;
532
- }
533
- // Parse ls -la output: permissions links owner group size date time name
534
- const match = line.match(/^([drwx-]+)\s+\d+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+\S+\s+(.+)$/);
535
- if (match) {
536
- const permissions = match[1];
537
- const size = parseInt(match[2], 10);
538
- const name = match[3];
539
- entries.push({
540
- name,
541
- type: permissions.startsWith('d') ? 'directory' : 'file',
542
- size,
543
- permissions,
544
- });
545
- }
546
- }
547
- return entries;
409
+ try {
410
+ const command = `docker exec ${this.config.containerId} sh -c "echo \\$SHELL"`;
411
+ const { stdout } = await this.executeHostCommand(command);
412
+ const shellPath = stdout.trim();
413
+ if (shellPath.includes("bash")) return "bash";
414
+ if (shellPath.includes("zsh")) return "zsh";
415
+ if (shellPath.includes("fish")) return "fish";
416
+ return "sh";
417
+ } catch {
418
+ return "sh";
548
419
  }
549
- /**
550
- * Parse search results from grep output
551
- */
552
- parseSearchResults(output) {
553
- const results = [];
554
- const lines = output.split('\n').filter(line => line.trim());
555
- for (const line of lines) {
556
- const match = line.match(/^(.+?):(\d+):(.+)$/);
557
- if (match) {
558
- results.push({
559
- file: match[1],
560
- line: parseInt(match[2], 10),
561
- content: match[3],
562
- });
563
- }
564
- }
565
- return results;
420
+ }
421
+ /**
422
+ * Detect the operating system type in the Docker container
423
+ */
424
+ async detectOSType() {
425
+ if (!this.config) {
426
+ return "linux";
566
427
  }
567
- /**
568
- * Execute a promise with a timeout
569
- */
570
- async executeWithTimeout(operation, timeoutMs, operationName) {
571
- return Promise.race([
572
- operation(),
573
- new Promise((_, reject) => setTimeout(() => reject(new Error(`${operationName} timed out after ${timeoutMs}ms`)), timeoutMs)),
574
- ]);
428
+ try {
429
+ const command = `docker exec ${this.config.containerId} uname -s`;
430
+ const { stdout } = await this.executeHostCommand(command);
431
+ const osName = stdout.trim().toLowerCase();
432
+ if (osName.includes("darwin")) return "macos";
433
+ if (osName.includes("linux")) return "linux";
434
+ return "linux";
435
+ } catch {
436
+ return "linux";
575
437
  }
576
- /**
577
- * Execute a command on the host (local or remote)
578
- */
579
- async executeHostCommand(command) {
580
- if (this.parentContext) {
581
- // Remote execution via parent context
582
- try {
583
- const result = await this.parentContext.handler.executeCommand(command);
584
- return {
585
- stdout: result.stdout,
586
- stderr: result.stderr,
587
- };
588
- }
589
- catch (error) {
590
- throw {
591
- message: error.message,
592
- code: error.exitCode || 1,
593
- stderr: error.stderr || error.message
594
- };
595
- }
596
- }
597
- // Local execution via child_process
598
- return execAsync(command);
438
+ }
439
+ /**
440
+ * Build a Docker exec command with working directory context
441
+ */
442
+ buildDockerCommand(command, pwdTag = "__CENTAURUS_PWD__") {
443
+ if (!this.config) {
444
+ throw new Error("Not connected to Docker container");
599
445
  }
600
- /**
601
- * Create a new instance of this handler
602
- */
603
- createNew() {
604
- return new DockerHandler();
446
+ const commandWithPwd = `${command}; echo "${pwdTag}:\\$(pwd)"`;
447
+ return `docker exec -w "${this.currentWorkingDirectory}" ${this.config.containerId} sh -c "${commandWithPwd.replace(/"/g, '\\"')}"`;
448
+ }
449
+ /**
450
+ * Resolve a path to an absolute path
451
+ */
452
+ resolveAbsolutePath(path) {
453
+ if (path.startsWith("/")) {
454
+ return path;
455
+ }
456
+ if (path.startsWith("~")) {
457
+ return path;
458
+ }
459
+ return `${this.currentWorkingDirectory}/${path}`;
460
+ }
461
+ /**
462
+ * Parse directory listing output
463
+ */
464
+ parseDirectoryListing(output) {
465
+ const entries = [];
466
+ const lines = output.split("\n").filter((line) => line.trim());
467
+ for (const line of lines) {
468
+ if (line.startsWith("total") || line.endsWith(" .") || line.endsWith(" ..")) {
469
+ continue;
470
+ }
471
+ const match = line.match(/^([drwx-]+)\s+\d+\s+\S+\s+\S+\s+(\d+)\s+\S+\s+\S+\s+\S+\s+(.+)$/);
472
+ if (match) {
473
+ const permissions = match[1];
474
+ const size = parseInt(match[2], 10);
475
+ const name = match[3];
476
+ entries.push({
477
+ name,
478
+ type: permissions.startsWith("d") ? "directory" : "file",
479
+ size,
480
+ permissions
481
+ });
482
+ }
483
+ }
484
+ return entries;
485
+ }
486
+ /**
487
+ * Parse search results from grep output
488
+ */
489
+ parseSearchResults(output) {
490
+ const results = [];
491
+ const lines = output.split("\n").filter((line) => line.trim());
492
+ for (const line of lines) {
493
+ const match = line.match(/^(.+?):(\d+):(.+)$/);
494
+ if (match) {
495
+ results.push({
496
+ file: match[1],
497
+ line: parseInt(match[2], 10),
498
+ content: match[3]
499
+ });
500
+ }
501
+ }
502
+ return results;
503
+ }
504
+ /**
505
+ * Execute a promise with a timeout
506
+ */
507
+ async executeWithTimeout(operation, timeoutMs, operationName) {
508
+ return Promise.race([
509
+ operation(),
510
+ new Promise(
511
+ (_, reject) => setTimeout(
512
+ () => reject(new Error(`${operationName} timed out after ${timeoutMs}ms`)),
513
+ timeoutMs
514
+ )
515
+ )
516
+ ]);
517
+ }
518
+ /**
519
+ * Execute a command on the host (local or remote)
520
+ */
521
+ async executeHostCommand(command) {
522
+ if (this.parentContext) {
523
+ try {
524
+ const result = await this.parentContext.handler.executeCommand(command);
525
+ return {
526
+ stdout: result.stdout,
527
+ stderr: result.stderr
528
+ };
529
+ } catch (error) {
530
+ throw {
531
+ message: error.message,
532
+ code: error.exitCode || 1,
533
+ stderr: error.stderr || error.message
534
+ };
535
+ }
605
536
  }
537
+ return execAsync(command);
538
+ }
539
+ /**
540
+ * Create a new instance of this handler
541
+ */
542
+ createNew() {
543
+ return new DockerHandler();
544
+ }
606
545
  }
546
+ export {
547
+ DockerHandler
548
+ };
607
549
  //# sourceMappingURL=docker-handler.js.map