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