mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-09 16:59:43 +02:00
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:
@@ -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.
|
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
|
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
|
||||||
|
|
||||||
|
|||||||
+28
-1
@@ -672,7 +672,8 @@ export class ScreenManager extends EventEmitter {
|
|||||||
// IMPORTANT: Must send text and carriage return as SEPARATE commands
|
// IMPORTANT: Must send text and carriage return as SEPARATE commands
|
||||||
// Sending them together doesn't work with Ink/Claude CLI
|
// Sending them together doesn't work with Ink/Claude CLI
|
||||||
const hasCarriageReturn = input.includes('\r');
|
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
|
// Escape the text part for shell using the helper function
|
||||||
const escapedText = shellEscape(textPart);
|
const escapedText = shellEscape(textPart);
|
||||||
@@ -684,9 +685,35 @@ export class ScreenManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send carriage return separately (Enter key for Ink)
|
// Send carriage return separately (Enter key for Ink)
|
||||||
|
// Use a synchronous sleep to ensure screen processes the text first
|
||||||
if (hasCarriageReturn) {
|
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')"`;
|
const crCmd = `screen -S ${screen.screenName} -p 0 -X stuff "$(printf '\\015')"`;
|
||||||
|
|
||||||
|
// 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 });
|
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;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user