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.
- package/dist/ai/types.js +0 -1
- package/dist/ai/types.js.map +1 -1
- package/dist/cli-adapter.js +5047 -5158
- package/dist/cli-adapter.js.map +1 -1
- package/dist/commands/CommandParser.js +372 -315
- package/dist/commands/CommandParser.js.map +1 -1
- package/dist/config/build-config.js +11 -42
- package/dist/config/build-config.js.map +1 -1
- package/dist/config/defaultConfig.js +94 -82
- package/dist/config/defaultConfig.js.map +1 -1
- package/dist/config/manager.js +144 -160
- package/dist/config/manager.js.map +1 -1
- package/dist/config/mcp-config-manager.js +411 -364
- package/dist/config/mcp-config-manager.js.map +1 -1
- package/dist/config/models.js +118 -185
- package/dist/config/models.js.map +1 -1
- package/dist/config/slash-commands.js +186 -184
- package/dist/config/slash-commands.js.map +1 -1
- package/dist/config/types.js +33 -26
- package/dist/config/types.js.map +1 -1
- package/dist/context/command-detector.js +63 -67
- package/dist/context/command-detector.js.map +1 -1
- package/dist/context/context-manager.js +533 -518
- package/dist/context/context-manager.js.map +1 -1
- package/dist/context/handlers/docker-handler.js +518 -576
- package/dist/context/handlers/docker-handler.js.map +1 -1
- package/dist/context/handlers/ssh-handler.js +1050 -1109
- package/dist/context/handlers/ssh-handler.js.map +1 -1
- package/dist/context/handlers/wsl-handler.js +558 -630
- package/dist/context/handlers/wsl-handler.js.map +1 -1
- package/dist/context/index.js +42 -6
- package/dist/context/index.js.map +1 -1
- package/dist/context/subshell-handler.js +0 -4
- package/dist/context/subshell-handler.js.map +1 -1
- package/dist/context/types.js +20 -31
- package/dist/context/types.js.map +1 -1
- package/dist/hooks/useConnectivity.js +13 -10
- package/dist/hooks/useConnectivity.js.map +1 -1
- package/dist/hooks/useTerminalDimensions.js +67 -79
- package/dist/hooks/useTerminalDimensions.js.map +1 -1
- package/dist/index.js +228 -251
- package/dist/index.js.map +1 -1
- package/dist/mcp/mcp-command-handler.js +297 -260
- package/dist/mcp/mcp-command-handler.js.map +1 -1
- package/dist/mcp/mcp-server-manager.js +139 -155
- package/dist/mcp/mcp-server-manager.js.map +1 -1
- package/dist/mcp/mcp-tool-wrapper.js +74 -94
- package/dist/mcp/mcp-tool-wrapper.js.map +1 -1
- package/dist/services/ai-autocomplete-agent.js +169 -181
- package/dist/services/ai-autocomplete-agent.js.map +1 -1
- package/dist/services/ai-context-injector.js +180 -93
- package/dist/services/ai-context-injector.js.map +1 -1
- package/dist/services/ai-service-client.js +513 -456
- package/dist/services/ai-service-client.js.map +1 -1
- package/dist/services/api-client.js +443 -441
- package/dist/services/api-client.js.map +1 -1
- package/dist/services/auth-handler.js +162 -198
- package/dist/services/auth-handler.js.map +1 -1
- package/dist/services/background-task-manager.js +258 -282
- package/dist/services/background-task-manager.js.map +1 -1
- package/dist/services/checkpoint-manager.js +1526 -1512
- package/dist/services/checkpoint-manager.js.map +1 -1
- package/dist/services/clipboard-service.js +151 -200
- package/dist/services/clipboard-service.js.map +1 -1
- package/dist/services/connectivity-manager.js +63 -65
- package/dist/services/connectivity-manager.js.map +1 -1
- package/dist/services/conversation-manager.js +118 -121
- package/dist/services/conversation-manager.js.map +1 -1
- package/dist/services/environment-context-injector.js +160 -187
- package/dist/services/environment-context-injector.js.map +1 -1
- package/dist/services/fast-context-agent.js +203 -243
- package/dist/services/fast-context-agent.js.map +1 -1
- package/dist/services/input-detection-agent.js +190 -202
- package/dist/services/input-detection-agent.js.map +1 -1
- package/dist/services/input-requirement-detector.js +155 -189
- package/dist/services/input-requirement-detector.js.map +1 -1
- package/dist/services/local-chat-storage.js +342 -365
- package/dist/services/local-chat-storage.js.map +1 -1
- package/dist/services/monitored-shell-manager.js +225 -233
- package/dist/services/monitored-shell-manager.js.map +1 -1
- package/dist/services/ollama-service.js +293 -310
- package/dist/services/ollama-service.js.map +1 -1
- package/dist/services/rules-storage.js +142 -0
- package/dist/services/rules-storage.js.map +1 -0
- package/dist/services/session-quota-manager.js +219 -235
- package/dist/services/session-quota-manager.js.map +1 -1
- package/dist/services/shell-input-agent.js +299 -334
- package/dist/services/shell-input-agent.js.map +1 -1
- package/dist/services/sub-agent-manager.js +459 -501
- package/dist/services/sub-agent-manager.js.map +1 -1
- package/dist/services/warpify-detector.js +133 -183
- package/dist/services/warpify-detector.js.map +1 -1
- package/dist/services/workflow-storage.js +202 -217
- package/dist/services/workflow-storage.js.map +1 -1
- package/dist/test-ssh-handler.js +148 -193
- package/dist/test-ssh-handler.js.map +1 -1
- package/dist/tools/add-mcp.js +161 -0
- package/dist/tools/add-mcp.js.map +1 -0
- package/dist/tools/background-command.js +240 -273
- package/dist/tools/background-command.js.map +1 -1
- package/dist/tools/command.js +447 -440
- package/dist/tools/command.js.map +1 -1
- package/dist/tools/create-image.js +172 -202
- package/dist/tools/create-image.js.map +1 -1
- package/dist/tools/enter-remote-session.js +169 -215
- package/dist/tools/enter-remote-session.js.map +1 -1
- package/dist/tools/fast-context.js +60 -67
- package/dist/tools/fast-context.js.map +1 -1
- package/dist/tools/file-ops.js +601 -572
- package/dist/tools/file-ops.js.map +1 -1
- package/dist/tools/find-files.js +262 -303
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/get-diff.js +423 -406
- package/dist/tools/get-diff.js.map +1 -1
- package/dist/tools/grep-search.js +966 -948
- package/dist/tools/grep-search.js.map +1 -1
- package/dist/tools/inspect-symbol.js +308 -323
- package/dist/tools/inspect-symbol.js.map +1 -1
- package/dist/tools/plan-mode.js +459 -503
- package/dist/tools/plan-mode.js.map +1 -1
- package/dist/tools/read-binary-file.js +160 -190
- package/dist/tools/read-binary-file.js.map +1 -1
- package/dist/tools/registry.js +100 -84
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/reproduce_issue.js +170 -151
- package/dist/tools/reproduce_issue.js.map +1 -1
- package/dist/tools/sub-agent.js +223 -228
- package/dist/tools/sub-agent.js.map +1 -1
- package/dist/tools/task-complete.js +28 -27
- package/dist/tools/task-complete.js.map +1 -1
- package/dist/tools/types.js +0 -1
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/validation.js +96 -118
- package/dist/tools/validation.js.map +1 -1
- package/dist/tools/web-search.js +194 -194
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/workflow-tool.js +77 -82
- package/dist/tools/workflow-tool.js.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/rule.js +1 -0
- package/dist/types/rule.js.map +1 -0
- package/dist/types/workflow.js +0 -7
- package/dist/types/workflow.js.map +1 -1
- package/dist/ui/components/AgentTimer.js +24 -25
- package/dist/ui/components/AgentTimer.js.map +1 -1
- package/dist/ui/components/App.js +3266 -3263
- package/dist/ui/components/App.js.map +1 -1
- package/dist/ui/components/AuthScreen.js +22 -34
- package/dist/ui/components/AuthScreen.js.map +1 -1
- package/dist/ui/components/AuthWelcomeScreen.js +30 -24
- package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
- package/dist/ui/components/Breadcrumbs.js +53 -82
- package/dist/ui/components/Breadcrumbs.js.map +1 -1
- package/dist/ui/components/CircularSelectInput.js +59 -67
- package/dist/ui/components/CircularSelectInput.js.map +1 -1
- package/dist/ui/components/ClipboardFileAutocomplete.js +78 -39
- package/dist/ui/components/ClipboardFileAutocomplete.js.map +1 -1
- package/dist/ui/components/CodeBlock.js +24 -42
- package/dist/ui/components/CodeBlock.js.map +1 -1
- package/dist/ui/components/ConfigViewer.js +18 -25
- package/dist/ui/components/ConfigViewer.js.map +1 -1
- package/dist/ui/components/ConfirmPrompt.js +49 -71
- package/dist/ui/components/ConfirmPrompt.js.map +1 -1
- package/dist/ui/components/ConnectionStatusMessage.js +32 -83
- package/dist/ui/components/ConnectionStatusMessage.js.map +1 -1
- package/dist/ui/components/ContextWindowIndicator.js +34 -49
- package/dist/ui/components/ContextWindowIndicator.js.map +1 -1
- package/dist/ui/components/DetailedPlanReviewScreen.js +104 -106
- package/dist/ui/components/DetailedPlanReviewScreen.js.map +1 -1
- package/dist/ui/components/DiffViewer.js +68 -121
- package/dist/ui/components/DiffViewer.js.map +1 -1
- package/dist/ui/components/ErrorBoundary.js +40 -48
- package/dist/ui/components/ErrorBoundary.js.map +1 -1
- package/dist/ui/components/FileCreationPreview.js +29 -60
- package/dist/ui/components/FileCreationPreview.js.map +1 -1
- package/dist/ui/components/FileOperation.js +34 -29
- package/dist/ui/components/FileOperation.js.map +1 -1
- package/dist/ui/components/FileTagAutocomplete.js +55 -25
- package/dist/ui/components/FileTagAutocomplete.js.map +1 -1
- package/dist/ui/components/FontRecommendation.js.map +1 -1
- package/dist/ui/components/GitDiffBreadcrumb.js +29 -0
- package/dist/ui/components/GitDiffBreadcrumb.js.map +1 -0
- package/dist/ui/components/InputBox.js +1620 -2150
- package/dist/ui/components/InputBox.js.map +1 -1
- package/dist/ui/components/InteractiveShell.js +234 -352
- package/dist/ui/components/InteractiveShell.js.map +1 -1
- package/dist/ui/components/KeyboardHelp.js +34 -35
- package/dist/ui/components/KeyboardHelp.js.map +1 -1
- package/dist/ui/components/LoadingIndicator.js +22 -25
- package/dist/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/ui/components/MCPAddScreen.js +40 -51
- package/dist/ui/components/MCPAddScreen.js.map +1 -1
- package/dist/ui/components/MCPListScreen.js +40 -48
- package/dist/ui/components/MCPListScreen.js.map +1 -1
- package/dist/ui/components/MCPServerListScreen.js +49 -56
- package/dist/ui/components/MCPServerListScreen.js.map +1 -1
- package/dist/ui/components/MarkdownRenderer.js +69 -96
- package/dist/ui/components/MarkdownRenderer.js.map +1 -1
- package/dist/ui/components/MessageBox.js +66 -48
- package/dist/ui/components/MessageBox.js.map +1 -1
- package/dist/ui/components/MessageDisplay.js +150 -142
- package/dist/ui/components/MessageDisplay.js.map +1 -1
- package/dist/ui/components/MonitorModeAIPanel.js +46 -65
- package/dist/ui/components/MonitorModeAIPanel.js.map +1 -1
- package/dist/ui/components/MultiLineInput.js +243 -277
- package/dist/ui/components/MultiLineInput.js.map +1 -1
- package/dist/ui/components/PasswordPrompt.js +37 -18
- package/dist/ui/components/PasswordPrompt.js.map +1 -1
- package/dist/ui/components/PlanAcceptedMessage.js +27 -38
- package/dist/ui/components/PlanAcceptedMessage.js.map +1 -1
- package/dist/ui/components/PlanReviewScreen.js +46 -50
- package/dist/ui/components/PlanReviewScreen.js.map +1 -1
- package/dist/ui/components/RulesEditorScreen.js +81 -0
- package/dist/ui/components/RulesEditorScreen.js.map +1 -0
- package/dist/ui/components/SelectPrompt.js +19 -8
- package/dist/ui/components/SelectPrompt.js.map +1 -1
- package/dist/ui/components/ShimmerText.js +44 -0
- package/dist/ui/components/ShimmerText.js.map +1 -0
- package/dist/ui/components/SlashCommandAutocomplete.js +49 -22
- package/dist/ui/components/SlashCommandAutocomplete.js.map +1 -1
- package/dist/ui/components/StatusBar.js +56 -87
- package/dist/ui/components/StatusBar.js.map +1 -1
- package/dist/ui/components/StreamingMessageDisplay.js +116 -99
- package/dist/ui/components/StreamingMessageDisplay.js.map +1 -1
- package/dist/ui/components/TaskCompletedMessage.js +28 -23
- package/dist/ui/components/TaskCompletedMessage.js.map +1 -1
- package/dist/ui/components/TaskProgressIndicator.js +44 -70
- package/dist/ui/components/TaskProgressIndicator.js.map +1 -1
- package/dist/ui/components/ThinkingDisplay.js +44 -41
- package/dist/ui/components/ThinkingDisplay.js.map +1 -1
- package/dist/ui/components/ToolExecutionMessage.js +772 -1326
- package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
- package/dist/ui/components/ToolExecutionStatus.js +53 -84
- package/dist/ui/components/ToolExecutionStatus.js.map +1 -1
- package/dist/ui/components/ToolResult.js +22 -15
- package/dist/ui/components/ToolResult.js.map +1 -1
- package/dist/ui/components/VersionUpdatePrompt.js +88 -120
- package/dist/ui/components/VersionUpdatePrompt.js.map +1 -1
- package/dist/ui/components/WelcomeBanner.js +176 -26
- package/dist/ui/components/WelcomeBanner.js.map +1 -1
- package/dist/ui/components/WorkflowCreatorScreen.js +94 -161
- package/dist/ui/components/WorkflowCreatorScreen.js.map +1 -1
- package/dist/utils/ansi-encoder.js +30 -61
- package/dist/utils/ansi-encoder.js.map +1 -1
- package/dist/utils/chat-formatter.js +327 -305
- package/dist/utils/chat-formatter.js.map +1 -1
- package/dist/utils/command-history.js +152 -174
- package/dist/utils/command-history.js.map +1 -1
- package/dist/utils/context-sanitizer.js +49 -112
- package/dist/utils/context-sanitizer.js.map +1 -1
- package/dist/utils/conversation-logger.js +292 -324
- package/dist/utils/conversation-logger.js.map +1 -1
- package/dist/utils/custom-commands-manager.js +126 -131
- package/dist/utils/custom-commands-manager.js.map +1 -1
- package/dist/utils/editor-utils.js +732 -837
- package/dist/utils/editor-utils.js.map +1 -1
- package/dist/utils/file.js +174 -213
- package/dist/utils/file.js.map +1 -1
- package/dist/utils/git-stats.js +169 -0
- package/dist/utils/git-stats.js.map +1 -0
- package/dist/utils/input-classifier.js +960 -482
- package/dist/utils/input-classifier.js.map +1 -1
- package/dist/utils/logger.js +48 -73
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/markdown-parser.js +277 -310
- package/dist/utils/markdown-parser.js.map +1 -1
- package/dist/utils/rule-reference-resolver.js +54 -0
- package/dist/utils/rule-reference-resolver.js.map +1 -0
- package/dist/utils/shell.js +144 -156
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/state.js +23 -22
- package/dist/utils/state.js.map +1 -1
- package/dist/utils/syntax-checker.js +279 -327
- package/dist/utils/syntax-checker.js.map +1 -1
- package/dist/utils/terminal-output.js +199 -302
- package/dist/utils/terminal-output.js.map +1 -1
- package/dist/utils/text-clipboard.js +47 -70
- package/dist/utils/text-clipboard.js.map +1 -1
- package/dist/utils/unicode-sanitizer.js +134 -197
- package/dist/utils/unicode-sanitizer.js.map +1 -1
- package/dist/utils/version-checker.js +46 -56
- package/dist/utils/version-checker.js.map +1 -1
- package/package.json +6 -4
- package/dist/ai/types.d.ts +0 -20
- package/dist/ai/types.d.ts.map +0 -1
- package/dist/cli-adapter.d.ts +0 -514
- package/dist/cli-adapter.d.ts.map +0 -1
- package/dist/commands/CommandParser.d.ts +0 -27
- package/dist/commands/CommandParser.d.ts.map +0 -1
- package/dist/config/build-config.d.ts +0 -42
- package/dist/config/build-config.d.ts.map +0 -1
- package/dist/config/defaultConfig.d.ts +0 -79
- package/dist/config/defaultConfig.d.ts.map +0 -1
- package/dist/config/manager.d.ts +0 -62
- package/dist/config/manager.d.ts.map +0 -1
- package/dist/config/mcp-config-manager.d.ts +0 -79
- package/dist/config/mcp-config-manager.d.ts.map +0 -1
- package/dist/config/models.d.ts +0 -83
- package/dist/config/models.d.ts.map +0 -1
- package/dist/config/slash-commands.d.ts +0 -23
- package/dist/config/slash-commands.d.ts.map +0 -1
- package/dist/config/types.d.ts +0 -35
- package/dist/config/types.d.ts.map +0 -1
- package/dist/context/command-detector.d.ts +0 -50
- package/dist/context/command-detector.d.ts.map +0 -1
- package/dist/context/context-manager.d.ts +0 -157
- package/dist/context/context-manager.d.ts.map +0 -1
- package/dist/context/handlers/docker-handler.d.ts +0 -130
- package/dist/context/handlers/docker-handler.d.ts.map +0 -1
- package/dist/context/handlers/ssh-handler.d.ts +0 -201
- package/dist/context/handlers/ssh-handler.d.ts.map +0 -1
- package/dist/context/handlers/wsl-handler.d.ts +0 -146
- package/dist/context/handlers/wsl-handler.d.ts.map +0 -1
- package/dist/context/index.d.ts +0 -8
- package/dist/context/index.d.ts.map +0 -1
- package/dist/context/subshell-handler.d.ts +0 -165
- package/dist/context/subshell-handler.d.ts.map +0 -1
- package/dist/context/types.d.ts +0 -70
- package/dist/context/types.d.ts.map +0 -1
- package/dist/hooks/useConnectivity.d.ts +0 -2
- package/dist/hooks/useConnectivity.d.ts.map +0 -1
- package/dist/hooks/useTerminalDimensions.d.ts +0 -41
- package/dist/hooks/useTerminalDimensions.d.ts.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/mcp/mcp-command-handler.d.ts +0 -47
- package/dist/mcp/mcp-command-handler.d.ts.map +0 -1
- package/dist/mcp/mcp-server-manager.d.ts +0 -30
- package/dist/mcp/mcp-server-manager.d.ts.map +0 -1
- package/dist/mcp/mcp-tool-wrapper.d.ts +0 -12
- package/dist/mcp/mcp-tool-wrapper.d.ts.map +0 -1
- package/dist/services/ai-autocomplete-agent.d.ts +0 -39
- package/dist/services/ai-autocomplete-agent.d.ts.map +0 -1
- package/dist/services/ai-context-injector.d.ts +0 -41
- package/dist/services/ai-context-injector.d.ts.map +0 -1
- package/dist/services/ai-service-client.d.ts +0 -128
- package/dist/services/ai-service-client.d.ts.map +0 -1
- package/dist/services/api-client.d.ts +0 -353
- package/dist/services/api-client.d.ts.map +0 -1
- package/dist/services/auth-handler.d.ts +0 -30
- package/dist/services/auth-handler.d.ts.map +0 -1
- package/dist/services/background-task-manager.d.ts +0 -114
- package/dist/services/background-task-manager.d.ts.map +0 -1
- package/dist/services/checkpoint-manager.d.ts +0 -204
- package/dist/services/checkpoint-manager.d.ts.map +0 -1
- package/dist/services/clipboard-service.d.ts +0 -37
- package/dist/services/clipboard-service.d.ts.map +0 -1
- package/dist/services/connectivity-manager.d.ts +0 -18
- package/dist/services/connectivity-manager.d.ts.map +0 -1
- package/dist/services/conversation-manager.d.ts +0 -73
- package/dist/services/conversation-manager.d.ts.map +0 -1
- package/dist/services/environment-context-injector.d.ts +0 -69
- package/dist/services/environment-context-injector.d.ts.map +0 -1
- package/dist/services/fast-context-agent.d.ts +0 -12
- package/dist/services/fast-context-agent.d.ts.map +0 -1
- package/dist/services/input-detection-agent.d.ts +0 -40
- package/dist/services/input-detection-agent.d.ts.map +0 -1
- package/dist/services/input-requirement-detector.d.ts +0 -28
- package/dist/services/input-requirement-detector.d.ts.map +0 -1
- package/dist/services/local-chat-storage.d.ts +0 -182
- package/dist/services/local-chat-storage.d.ts.map +0 -1
- package/dist/services/monitored-shell-manager.d.ts +0 -120
- package/dist/services/monitored-shell-manager.d.ts.map +0 -1
- package/dist/services/ollama-service.d.ts +0 -197
- package/dist/services/ollama-service.d.ts.map +0 -1
- package/dist/services/session-quota-manager.d.ts +0 -101
- package/dist/services/session-quota-manager.d.ts.map +0 -1
- package/dist/services/shell-input-agent.d.ts +0 -89
- package/dist/services/shell-input-agent.d.ts.map +0 -1
- package/dist/services/sub-agent-manager.d.ts +0 -140
- package/dist/services/sub-agent-manager.d.ts.map +0 -1
- package/dist/services/warpify-detector.d.ts +0 -43
- package/dist/services/warpify-detector.d.ts.map +0 -1
- package/dist/services/workflow-storage.d.ts +0 -72
- package/dist/services/workflow-storage.d.ts.map +0 -1
- package/dist/test-ssh-handler.d.ts +0 -8
- package/dist/test-ssh-handler.d.ts.map +0 -1
- package/dist/tools/background-command.d.ts +0 -11
- package/dist/tools/background-command.d.ts.map +0 -1
- package/dist/tools/command.d.ts +0 -3
- package/dist/tools/command.d.ts.map +0 -1
- package/dist/tools/create-image.d.ts +0 -10
- package/dist/tools/create-image.d.ts.map +0 -1
- package/dist/tools/enter-remote-session.d.ts +0 -48
- package/dist/tools/enter-remote-session.d.ts.map +0 -1
- package/dist/tools/fast-context.d.ts +0 -3
- package/dist/tools/fast-context.d.ts.map +0 -1
- package/dist/tools/file-ops.d.ts +0 -7
- package/dist/tools/file-ops.d.ts.map +0 -1
- package/dist/tools/find-files.d.ts +0 -49
- package/dist/tools/find-files.d.ts.map +0 -1
- package/dist/tools/get-diff.d.ts +0 -14
- package/dist/tools/get-diff.d.ts.map +0 -1
- package/dist/tools/grep-search.d.ts +0 -155
- package/dist/tools/grep-search.d.ts.map +0 -1
- package/dist/tools/inspect-symbol.d.ts +0 -32
- package/dist/tools/inspect-symbol.d.ts.map +0 -1
- package/dist/tools/plan-mode.d.ts +0 -140
- package/dist/tools/plan-mode.d.ts.map +0 -1
- package/dist/tools/read-binary-file.d.ts +0 -10
- package/dist/tools/read-binary-file.d.ts.map +0 -1
- package/dist/tools/registry.d.ts +0 -31
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/reproduce_issue.d.ts +0 -2
- package/dist/tools/reproduce_issue.d.ts.map +0 -1
- package/dist/tools/sub-agent.d.ts +0 -9
- package/dist/tools/sub-agent.d.ts.map +0 -1
- package/dist/tools/task-complete.d.ts +0 -3
- package/dist/tools/task-complete.d.ts.map +0 -1
- package/dist/tools/types.d.ts +0 -40
- package/dist/tools/types.d.ts.map +0 -1
- package/dist/tools/validation.d.ts +0 -47
- package/dist/tools/validation.d.ts.map +0 -1
- package/dist/tools/web-search.d.ts +0 -24
- package/dist/tools/web-search.d.ts.map +0 -1
- package/dist/tools/workflow-tool.d.ts +0 -11
- package/dist/tools/workflow-tool.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -123
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/workflow.d.ts +0 -110
- package/dist/types/workflow.d.ts.map +0 -1
- package/dist/ui/components/AgentTimer.d.ts +0 -7
- package/dist/ui/components/AgentTimer.d.ts.map +0 -1
- package/dist/ui/components/App.d.ts +0 -197
- package/dist/ui/components/App.d.ts.map +0 -1
- package/dist/ui/components/AuthScreen.d.ts +0 -8
- package/dist/ui/components/AuthScreen.d.ts.map +0 -1
- package/dist/ui/components/AuthWelcomeScreen.d.ts +0 -8
- package/dist/ui/components/AuthWelcomeScreen.d.ts.map +0 -1
- package/dist/ui/components/Breadcrumbs.d.ts +0 -13
- package/dist/ui/components/Breadcrumbs.d.ts.map +0 -1
- package/dist/ui/components/CircularSelectInput.d.ts +0 -24
- package/dist/ui/components/CircularSelectInput.d.ts.map +0 -1
- package/dist/ui/components/ClipboardFileAutocomplete.d.ts +0 -10
- package/dist/ui/components/ClipboardFileAutocomplete.d.ts.map +0 -1
- package/dist/ui/components/CodeBlock.d.ts +0 -9
- package/dist/ui/components/CodeBlock.d.ts.map +0 -1
- package/dist/ui/components/ConfigViewer.d.ts +0 -11
- package/dist/ui/components/ConfigViewer.d.ts.map +0 -1
- package/dist/ui/components/ConfirmPrompt.d.ts +0 -13
- package/dist/ui/components/ConfirmPrompt.d.ts.map +0 -1
- package/dist/ui/components/ConnectionStatusMessage.d.ts +0 -17
- package/dist/ui/components/ConnectionStatusMessage.d.ts.map +0 -1
- package/dist/ui/components/ContextWindowIndicator.d.ts +0 -8
- package/dist/ui/components/ContextWindowIndicator.d.ts.map +0 -1
- package/dist/ui/components/DetailedPlanReviewScreen.d.ts +0 -17
- package/dist/ui/components/DetailedPlanReviewScreen.d.ts.map +0 -1
- package/dist/ui/components/DiffViewer.d.ts +0 -9
- package/dist/ui/components/DiffViewer.d.ts.map +0 -1
- package/dist/ui/components/ErrorBoundary.d.ts +0 -17
- package/dist/ui/components/ErrorBoundary.d.ts.map +0 -1
- package/dist/ui/components/FileCreationPreview.d.ts +0 -8
- package/dist/ui/components/FileCreationPreview.d.ts.map +0 -1
- package/dist/ui/components/FileOperation.d.ts +0 -10
- package/dist/ui/components/FileOperation.d.ts.map +0 -1
- package/dist/ui/components/FileTagAutocomplete.d.ts +0 -11
- package/dist/ui/components/FileTagAutocomplete.d.ts.map +0 -1
- package/dist/ui/components/FontRecommendation.d.ts +0 -1
- package/dist/ui/components/FontRecommendation.d.ts.map +0 -1
- package/dist/ui/components/InputBox.d.ts +0 -42
- package/dist/ui/components/InputBox.d.ts.map +0 -1
- package/dist/ui/components/InteractiveShell.d.ts +0 -30
- package/dist/ui/components/InteractiveShell.d.ts.map +0 -1
- package/dist/ui/components/KeyboardHelp.d.ts +0 -7
- package/dist/ui/components/KeyboardHelp.d.ts.map +0 -1
- package/dist/ui/components/LoadingIndicator.d.ts +0 -3
- package/dist/ui/components/LoadingIndicator.d.ts.map +0 -1
- package/dist/ui/components/MCPAddScreen.d.ts +0 -13
- package/dist/ui/components/MCPAddScreen.d.ts.map +0 -1
- package/dist/ui/components/MCPListScreen.d.ts +0 -17
- package/dist/ui/components/MCPListScreen.d.ts.map +0 -1
- package/dist/ui/components/MCPServerListScreen.d.ts +0 -16
- package/dist/ui/components/MCPServerListScreen.d.ts.map +0 -1
- package/dist/ui/components/MarkdownRenderer.d.ts +0 -8
- package/dist/ui/components/MarkdownRenderer.d.ts.map +0 -1
- package/dist/ui/components/MessageBox.d.ts +0 -10
- package/dist/ui/components/MessageBox.d.ts.map +0 -1
- package/dist/ui/components/MessageDisplay.d.ts +0 -14
- package/dist/ui/components/MessageDisplay.d.ts.map +0 -1
- package/dist/ui/components/MonitorModeAIPanel.d.ts +0 -23
- package/dist/ui/components/MonitorModeAIPanel.d.ts.map +0 -1
- package/dist/ui/components/MultiLineInput.d.ts +0 -13
- package/dist/ui/components/MultiLineInput.d.ts.map +0 -1
- package/dist/ui/components/PasswordPrompt.d.ts +0 -9
- package/dist/ui/components/PasswordPrompt.d.ts.map +0 -1
- package/dist/ui/components/PlanAcceptedMessage.d.ts +0 -20
- package/dist/ui/components/PlanAcceptedMessage.d.ts.map +0 -1
- package/dist/ui/components/PlanReviewScreen.d.ts +0 -14
- package/dist/ui/components/PlanReviewScreen.d.ts.map +0 -1
- package/dist/ui/components/SelectPrompt.d.ts +0 -12
- package/dist/ui/components/SelectPrompt.d.ts.map +0 -1
- package/dist/ui/components/SlashCommandAutocomplete.d.ts +0 -13
- package/dist/ui/components/SlashCommandAutocomplete.d.ts.map +0 -1
- package/dist/ui/components/StatusBar.d.ts +0 -14
- package/dist/ui/components/StatusBar.d.ts.map +0 -1
- package/dist/ui/components/StreamingMessageDisplay.d.ts +0 -15
- package/dist/ui/components/StreamingMessageDisplay.d.ts.map +0 -1
- package/dist/ui/components/TaskCompletedMessage.d.ts +0 -14
- package/dist/ui/components/TaskCompletedMessage.d.ts.map +0 -1
- package/dist/ui/components/TaskProgressIndicator.d.ts +0 -18
- package/dist/ui/components/TaskProgressIndicator.d.ts.map +0 -1
- package/dist/ui/components/ThinkingDisplay.d.ts +0 -15
- package/dist/ui/components/ThinkingDisplay.d.ts.map +0 -1
- package/dist/ui/components/ToolExecutionMessage.d.ts +0 -8
- package/dist/ui/components/ToolExecutionMessage.d.ts.map +0 -1
- package/dist/ui/components/ToolExecutionStatus.d.ts +0 -10
- package/dist/ui/components/ToolExecutionStatus.d.ts.map +0 -1
- package/dist/ui/components/ToolResult.d.ts +0 -10
- package/dist/ui/components/ToolResult.d.ts.map +0 -1
- package/dist/ui/components/VersionUpdatePrompt.d.ts +0 -9
- package/dist/ui/components/VersionUpdatePrompt.d.ts.map +0 -1
- package/dist/ui/components/WelcomeBanner.d.ts +0 -3
- package/dist/ui/components/WelcomeBanner.d.ts.map +0 -1
- package/dist/ui/components/WorkflowCreatorScreen.d.ts +0 -25
- package/dist/ui/components/WorkflowCreatorScreen.d.ts.map +0 -1
- package/dist/utils/ansi-encoder.d.ts +0 -7
- package/dist/utils/ansi-encoder.d.ts.map +0 -1
- package/dist/utils/chat-formatter.d.ts +0 -12
- package/dist/utils/chat-formatter.d.ts.map +0 -1
- package/dist/utils/command-history.d.ts +0 -24
- package/dist/utils/command-history.d.ts.map +0 -1
- package/dist/utils/context-sanitizer.d.ts +0 -50
- package/dist/utils/context-sanitizer.d.ts.map +0 -1
- package/dist/utils/conversation-logger.d.ts +0 -142
- package/dist/utils/conversation-logger.d.ts.map +0 -1
- package/dist/utils/custom-commands-manager.d.ts +0 -59
- package/dist/utils/custom-commands-manager.d.ts.map +0 -1
- package/dist/utils/editor-utils.d.ts +0 -101
- package/dist/utils/editor-utils.d.ts.map +0 -1
- package/dist/utils/file.d.ts +0 -61
- package/dist/utils/file.d.ts.map +0 -1
- package/dist/utils/input-classifier.d.ts +0 -25
- package/dist/utils/input-classifier.d.ts.map +0 -1
- package/dist/utils/logger.d.ts +0 -17
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/markdown-parser.d.ts +0 -60
- package/dist/utils/markdown-parser.d.ts.map +0 -1
- package/dist/utils/shell.d.ts +0 -47
- package/dist/utils/shell.d.ts.map +0 -1
- package/dist/utils/state.d.ts +0 -13
- package/dist/utils/state.d.ts.map +0 -1
- package/dist/utils/syntax-checker.d.ts +0 -24
- package/dist/utils/syntax-checker.d.ts.map +0 -1
- package/dist/utils/terminal-output.d.ts +0 -25
- package/dist/utils/terminal-output.d.ts.map +0 -1
- package/dist/utils/text-clipboard.d.ts +0 -12
- package/dist/utils/text-clipboard.d.ts.map +0 -1
- package/dist/utils/unicode-sanitizer.d.ts +0 -44
- package/dist/utils/unicode-sanitizer.d.ts.map +0 -1
- package/dist/utils/version-checker.d.ts +0 -14
- package/dist/utils/version-checker.d.ts.map +0 -1
|
@@ -1,607 +1,549 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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
|
-
|
|
365
|
-
*/
|
|
366
|
-
async getOSType() {
|
|
367
|
-
return this.osType;
|
|
303
|
+
if (!this.config) {
|
|
304
|
+
return "/";
|
|
368
305
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
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
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
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
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
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
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
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
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|