From 6b48e73607acee7ded03507eac924c26e989846a Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 12 Nov 2025 09:21:17 +0100 Subject: [PATCH] Fix session selector: handle Ctrl+C and viewport width - Add SIGINT handler to allow Ctrl+C to exit during session selection - Remove hardcoded 60-char truncation, let SelectList handle dynamic truncation - Simplify date format (5m, 2h, 3d instead of "5m ago") - Make metadata more compact (5msg instead of "5 msgs") --- packages/coding-agent/src/main.ts | 30 +++++++++++++++---- .../coding-agent/src/tui/session-selector.ts | 24 +++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index 1afe21a2..55744b85 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -124,17 +124,37 @@ async function selectSession(sessionManager: SessionManager): Promise { const ui = new TUI(new ProcessTerminal()); let selectedPath: string | null = null; + let resolved = false; + + // Handle Ctrl+C + const handleSigint = () => { + if (!resolved) { + resolved = true; + ui.stop(); + process.exit(0); + } + }; + + process.on("SIGINT", handleSigint); const selector = new SessionSelectorComponent( sessionManager, (path: string) => { - selectedPath = path; - ui.stop(); - resolve(path); + if (!resolved) { + resolved = true; + selectedPath = path; + process.removeListener("SIGINT", handleSigint); + ui.stop(); + resolve(path); + } }, () => { - ui.stop(); - resolve(null); + if (!resolved) { + resolved = true; + process.removeListener("SIGINT", handleSigint); + ui.stop(); + resolve(null); + } }, ); diff --git a/packages/coding-agent/src/tui/session-selector.ts b/packages/coding-agent/src/tui/session-selector.ts index d8006ec7..ebc5aaae 100644 --- a/packages/coding-agent/src/tui/session-selector.ts +++ b/packages/coding-agent/src/tui/session-selector.ts @@ -54,29 +54,29 @@ export class SessionSelectorComponent extends Container { const diffHours = Math.floor(diffMs / 3600000); const diffDays = Math.floor(diffMs / 86400000); - if (diffMins < 1) return "just now"; - if (diffMins < 60) return `${diffMins}m ago`; - if (diffHours < 24) return `${diffHours}h ago`; - if (diffDays === 1) return "yesterday"; - if (diffDays < 7) return `${diffDays}d ago`; + if (diffMins < 1) return "now"; + if (diffMins < 60) return `${diffMins}m`; + if (diffHours < 24) return `${diffHours}h`; + if (diffDays === 1) return "1d"; + if (diffDays < 7) return `${diffDays}d`; // Fallback to date string return date.toLocaleDateString(); }; - // Truncate first message to single line - const truncatedMessage = session.firstMessage.replace(/\n/g, " ").trim(); + // Normalize first message to single line + const normalizedMessage = session.firstMessage.replace(/\n/g, " ").trim(); - // Build description with metadata - const created = formatDate(session.created); + // Build description with metadata (single line, compact format) const modified = formatDate(session.modified); - const msgCount = `${session.messageCount} msg${session.messageCount !== 1 ? "s" : ""}`; + const msgCount = `${session.messageCount}msg`; - const description = `${truncatedMessage}\n${chalk.dim(`Created: ${created} • Modified: ${modified} • ${msgCount}`)}`; + // Keep description compact: "modified • count" + const description = `${modified} • ${msgCount}`; return { value: session.path, - label: truncatedMessage.substring(0, 80), + label: normalizedMessage, // Let SelectList handle truncation based on actual width description, }; });