fix: wait for WebSocket connection before sending command

Make connectTerminal() return a Promise that resolves when the
WebSocket connection is established, ensuring commands are sent
only after the terminal is ready.

Root cause:
- connectTerminal() created WebSocket but returned immediately
- 500ms delay wasn't reliable - WebSocket might not be open yet
- Command was sent before connection was ready, causing it to fail silently

Fix:
- Wrap WebSocket creation in Promise
- Resolve Promise in ws.onopen callback
- Reject on ws.onerror
- Remove unnecessary 500ms delay

Now when "Claude Code CLI" terminal type is selected:
1. WebSocket connection is established
2. We wait for connection to be ready
3. Command is sent immediately
4. claude --dangerously-skip-permissions launches reliably

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
uroma
2026-01-19 18:38:14 +00:00
Unverified
parent 3fac4efce3
commit f57b01c82b

View File

@@ -221,10 +221,9 @@ class TerminalManager {
// Handle terminal type specific initialization // Handle terminal type specific initialization
if (selectedTerminalType === 'claude-cli') { if (selectedTerminalType === 'claude-cli') {
// Wait a moment for terminal to be ready
await new Promise(resolve => setTimeout(resolve, 500));
// Launch Claude CLI with skip permissions flag // Launch Claude CLI with skip permissions flag
// Note: Keep mode as 'mixed' since we're not attaching to a session // Note: Keep mode as 'mixed' since we're not attaching to a session
// WebSocket is already connected (await connectTerminal), so no delay needed
await this.launchCommand(terminalId, 'claude --dangerously-skip-permissions\n'); await this.launchCommand(terminalId, 'claude --dangerously-skip-permissions\n');
if (!silent) { if (!silent) {
@@ -768,35 +767,39 @@ class TerminalManager {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${protocol}//${window.location.host}/claude/api/terminals/${terminalId}/ws`; const wsUrl = `${protocol}//${window.location.host}/claude/api/terminals/${terminalId}/ws`;
try { return new Promise((resolve, reject) => {
const ws = new WebSocket(wsUrl); try {
const ws = new WebSocket(wsUrl);
ws.onopen = () => { ws.onopen = () => {
console.log(`[TerminalManager] Connected to terminal ${terminalId}`); console.log(`[TerminalManager] Connected to terminal ${terminalId}`);
}; resolve();
};
ws.onmessage = (event) => { ws.onmessage = (event) => {
const message = JSON.parse(event.data); const message = JSON.parse(event.data);
this.handleTerminalMessage(terminalId, message); this.handleTerminalMessage(terminalId, message);
}; };
ws.onerror = (error) => { ws.onerror = (error) => {
console.error(`[TerminalManager] WebSocket error for terminal ${terminalId}:`, error); console.error(`[TerminalManager] WebSocket error for terminal ${terminalId}:`, error);
}; reject(error);
};
ws.onclose = () => { ws.onclose = () => {
console.log(`[TerminalManager] WebSocket closed for terminal ${terminalId}`); console.log(`[TerminalManager] WebSocket closed for terminal ${terminalId}`);
}; };
// Store WebSocket // Store WebSocket
const terminal = this.terminals.get(terminalId); const terminal = this.terminals.get(terminalId);
if (terminal) { if (terminal) {
terminal.ws = ws; terminal.ws = ws;
}
} catch (error) {
console.error('[TerminalManager] Error connecting WebSocket:', error);
reject(error);
} }
} catch (error) { });
console.error('[TerminalManager] Error connecting WebSocket:', error);
throw error;
}
} }
/** /**