fix: improve screen sendInput reliability with retry logic (v0.1339)

- Add 100ms delay between text and carriage return to prevent race conditions
- Add retry logic (up to 3 attempts) for carriage return with increasing delays
- Trim trailing whitespace from text to avoid spurious spaces
- Better error logging for debugging input delivery issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-25 05:52:34 +01:00
co-authored by Claude Opus 4.5
parent 0f9caa9d29
commit 6dba5e9671
2 changed files with 30 additions and 3 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
Claudeman is a Claude Code session manager with a web interface and autonomous Ralph Loop. It spawns Claude CLI processes via PTY, streams output in real-time via SSE, and supports scheduled/timed runs.
**Version**: 0.1338
**Version**: 0.1339
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
+29 -2
View File
@@ -672,7 +672,8 @@ export class ScreenManager extends EventEmitter {
// IMPORTANT: Must send text and carriage return as SEPARATE commands
// Sending them together doesn't work with Ink/Claude CLI
const hasCarriageReturn = input.includes('\r');
const textPart = input.replace(/\r/g, '').replace(/\n/g, '');
// Remove control characters and trim trailing whitespace to avoid spurious spaces
const textPart = input.replace(/\r/g, '').replace(/\n/g, '').trimEnd();
// Escape the text part for shell using the helper function
const escapedText = shellEscape(textPart);
@@ -684,9 +685,35 @@ export class ScreenManager extends EventEmitter {
}
// Send carriage return separately (Enter key for Ink)
// Use a synchronous sleep to ensure screen processes the text first
if (hasCarriageReturn) {
// Delay to let screen process the text before sending Enter
// This prevents race conditions where Enter arrives before the text is processed
// 100ms is needed for reliability - screen's internal buffering can be slow
if (escapedText) {
execSync('sleep 0.1', { timeout: 1000 });
}
const crCmd = `screen -S ${screen.screenName} -p 0 -X stuff "$(printf '\\015')"`;
execSync(crCmd, { encoding: 'utf-8', timeout: 5000 });
// Try up to 3 times with increasing delays
let success = false;
for (let attempt = 1; attempt <= 3 && !success; attempt++) {
try {
execSync(crCmd, { encoding: 'utf-8', timeout: 5000 });
success = true;
} catch (crErr) {
console.warn(`[ScreenManager] Carriage return attempt ${attempt}/3 failed`);
if (attempt < 3) {
execSync(`sleep 0.${attempt}`, { timeout: 1000 }); // 0.1s, 0.2s delays
}
}
}
if (!success) {
console.error('[ScreenManager] All carriage return attempts failed');
return false;
}
}
return true;