From de8952d34a490e6f1ded02c8f6c3fe2f41ae6b82 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 20 Jun 2025 05:07:56 +0200 Subject: [PATCH] feat: highlight session cards with orange border when 'esc to interrupt' is detected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add checkForEscPrompt() method to scan buffer content on each update - Emit 'esc-prompt-change' event when prompt presence changes - Apply orange border to session card when prompt is detected - Case-insensitive search for 'esc to interrupt' text 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- web/src/client/components/session-card.ts | 11 +++++-- .../client/components/vibe-terminal-buffer.ts | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/web/src/client/components/session-card.ts b/web/src/client/components/session-card.ts index cc528fbe..073c65a7 100644 --- a/web/src/client/components/session-card.ts +++ b/web/src/client/components/session-card.ts @@ -27,6 +27,7 @@ export class SessionCard extends LitElement { @property({ type: Object }) session!: Session; @state() private killing = false; @state() private killingFrame = 0; + @state() private hasEscPrompt = false; private killingInterval: number | null = null; @@ -47,6 +48,10 @@ export class SessionCard extends LitElement { ); } + private handleEscPromptChange(event: CustomEvent) { + this.hasEscPrompt = event.detail.hasEscPrompt; + } + private async handleKillClick(e: Event) { e.stopPropagation(); e.preventDefault(); @@ -151,10 +156,9 @@ export class SessionCard extends LitElement { render() { return html`
@@ -211,6 +215,7 @@ export class SessionCard extends LitElement { .sessionId=${this.session.id} class="w-full h-full" style="pointer-events: none;" + @esc-prompt-change=${this.handleEscPromptChange} > `}
diff --git a/web/src/client/components/vibe-terminal-buffer.ts b/web/src/client/components/vibe-terminal-buffer.ts index 3345a63a..c96d5285 100644 --- a/web/src/client/components/vibe-terminal-buffer.ts +++ b/web/src/client/components/vibe-terminal-buffer.ts @@ -25,6 +25,7 @@ export class VibeTerminalBuffer extends LitElement { @state() private error: string | null = null; @state() private displayedFontSize = 14; @state() private visibleRows = 0; + @state() private containsEscPrompt = false; private container: HTMLElement | null = null; private resizeObserver: ResizeObserver | null = null; @@ -122,6 +123,9 @@ export class VibeTerminalBuffer extends LitElement { this.buffer = snapshot; this.error = null; + // Check if buffer contains "esc to interrupt" text + this.checkForEscPrompt(); + // Recalculate dimensions now that we have the actual cols this.calculateDimensions(); @@ -130,6 +134,35 @@ export class VibeTerminalBuffer extends LitElement { }); } + private checkForEscPrompt() { + if (!this.buffer) { + this.containsEscPrompt = false; + return; + } + + // Check if any line contains "esc to interrupt" (case insensitive) + const searchText = 'esc to interrupt'; + const found = this.buffer.cells.some((row) => { + const lineText = row + .map((cell) => cell.char) + .join('') + .toLowerCase(); + return lineText.includes(searchText); + }); + + if (found !== this.containsEscPrompt) { + this.containsEscPrompt = found; + // Dispatch event to notify parent + this.dispatchEvent( + new CustomEvent('esc-prompt-change', { + detail: { hasEscPrompt: found }, + bubbles: true, + composed: true, + }) + ); + } + } + private unsubscribeFromBuffer() { if (this.unsubscribe) { this.unsubscribe();