fix: terminal command execution via HTTP POST workaround
The WebSocket send mechanism fails with close code 1006 when client tries to send data to server. Server never receives the message, indicating a network/proxy layer issue that couldn't be fixed through code changes or nginx configuration. Solution: Bypass WebSocket send entirely by using HTTP POST to send commands directly to the PTY. Changes: - Added sendTerminalInput() method to terminal-service.js that writes directly to PTY, bypassing WebSocket - Added POST endpoint /claude/api/terminals/:id/input to server.js - Modified launchCommand() in terminal.js to use fetch() with HTTP POST instead of WebSocket.send() The WebSocket receive direction still works (server→client for output display), only send direction (client→server for commands) is bypassed. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -683,7 +683,7 @@ class TerminalManager {
|
||||
|
||||
/**
|
||||
* Launch a command in the terminal
|
||||
* Waits for terminal to be ready before sending command
|
||||
* Uses HTTP POST as workaround for WebSocket send issue
|
||||
*/
|
||||
async launchCommand(terminalId, command) {
|
||||
this.debugLog('CMD', `launchCommand called: terminalId=${terminalId}, command="${command.trim()}"`);
|
||||
@@ -700,44 +700,30 @@ class TerminalManager {
|
||||
|
||||
this.debugLog('CMD', `Terminal ${terminalId} is ready!`);
|
||||
|
||||
// NO DELAY - send command immediately to avoid WebSocket closure
|
||||
this.debugLog('CMD', `Sending command immediately without delay...`);
|
||||
|
||||
const terminal = this.terminals.get(terminalId);
|
||||
if (!terminal) {
|
||||
this.debugLog('ERROR', `Terminal ${terminalId} not found in map`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!terminal.ws) {
|
||||
this.debugLog('ERROR', `WebSocket not set for terminal ${terminalId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check WebSocket state
|
||||
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
|
||||
this.debugLog('CMD', `WebSocket state: ${readyStates[terminal.ws.readyState]} (${terminal.ws.readyState})`);
|
||||
|
||||
if (terminal.ws.readyState !== WebSocket.OPEN) {
|
||||
this.debugLog('ERROR', `Cannot send - WebSocket not open`, {
|
||||
wsState: terminal.ws.readyState,
|
||||
stateName: readyStates[terminal.ws.readyState]
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Send command to terminal immediately
|
||||
const message = JSON.stringify({
|
||||
type: 'input',
|
||||
data: command
|
||||
});
|
||||
this.debugLog('CMD', `Sending to WebSocket: ${message}`);
|
||||
// Use HTTP POST instead of WebSocket send (bypasses proxy issue)
|
||||
this.debugLog('CMD', `Sending command via HTTP POST: ${command.trim()}`);
|
||||
|
||||
try {
|
||||
terminal.ws.send(message);
|
||||
this.debugLog('CMD', `Command sent to terminal ${terminalId}: ${command.trim()}`);
|
||||
const res = await fetch(`/claude/api/terminals/${terminalId}/input`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ data: command })
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
||||
}
|
||||
|
||||
const result = await res.json();
|
||||
|
||||
if (result.success) {
|
||||
this.debugLog('CMD', `Command sent to terminal ${terminalId} via HTTP: ${command.trim()}`);
|
||||
} else {
|
||||
this.debugLog('ERROR', `Failed to send command: ${result.error}`);
|
||||
showToast(`Failed to send command: ${result.error}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
this.debugLog('ERROR', `Failed to send command`, { error: error.message, name: error.name });
|
||||
this.debugLog('ERROR', `HTTP POST failed:`, { error: error.message });
|
||||
showToast(`Failed to send command: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user