From 360497d39dd73ae15c8d1bddcb610b8a332e375b Mon Sep 17 00:00:00 2001 From: Wooseong Kim Date: Sat, 19 Sep 2026 19:53:52 +0900 Subject: [PATCH] fix(antigravity): do not treat a wrap continuation caret as ready An unsent composer can show `> draft` then an indented `>`. That continuation is not an empty input box, so tui-idle must stay false. --- src/main/runtime/terminal-wait-detection.test.ts | 14 ++++++++++++++ src/main/runtime/terminal-wait-detection.ts | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main/runtime/terminal-wait-detection.test.ts b/src/main/runtime/terminal-wait-detection.test.ts index ee1470c472a..78d4945f2b2 100644 --- a/src/main/runtime/terminal-wait-detection.test.ts +++ b/src/main/runtime/terminal-wait-detection.test.ts @@ -408,6 +408,20 @@ describe('Antigravity readiness does not absorb its own startup dialog', () => { expect(isKnownReadyPromptPreview(waitText)).toBe(true) }) + it('rejects a visible unsent draft whose wrap continuation is a bare caret', () => { + const waitText = waitTextFor([ + 'Antigravity CLI 1.2.1', + 'Gemini 3.7 Flash (Low)', + '────────────────────────────────────────', + '> abc', + ' >', + '────────────────────────────────────────', + 'Gemini 3.7 Flash · low' + ]) + + expect(isKnownReadyPromptPreview(waitText)).toBe(false) + }) + // Ratchet: these dialogs must remain unready because their selection row is not a bare caret. const SILENT_STARTUP_DIALOGS: { name: string; lines: string[] }[] = [ { diff --git a/src/main/runtime/terminal-wait-detection.ts b/src/main/runtime/terminal-wait-detection.ts index 9db0a5d38a5..ebfcc5eaccf 100644 --- a/src/main/runtime/terminal-wait-detection.ts +++ b/src/main/runtime/terminal-wait-detection.ts @@ -143,8 +143,9 @@ function findAntigravityReadyPromptIndex(normalized: string): number | null { } let lineStart = headerIndex let promptIndex: number | null = null + let previousNonEmpty: { start: number; end: number } | null = null - // Why: logo glyphs can prefix any model, while the standalone composer caret is the stable ready marker across model choices. + // Why: a column-0 caret is ready; an indented `>` under `> draft` is a wrap, not an empty box. for (let cursor = headerIndex; cursor <= normalized.length; cursor += 1) { if (cursor < normalized.length && normalized.charCodeAt(cursor) !== 10) { continue @@ -158,9 +159,19 @@ function findAntigravityReadyPromptIndex(normalized: string): number | null { trimmedEnd -= 1 } if (lineStart > headerIndex && trimmedStart < trimmedEnd) { - if (trimmedEnd - trimmedStart === 1 && normalized.charCodeAt(trimmedStart) === 62) { + if ( + trimmedEnd - trimmedStart === 1 && + normalized.charCodeAt(trimmedStart) === 62 && + trimmedStart === lineStart && + !( + previousNonEmpty !== null && + normalized.charCodeAt(previousNonEmpty.start) === 62 && + previousNonEmpty.end - previousNonEmpty.start > 1 + ) + ) { promptIndex = trimmedStart } + previousNonEmpty = { start: trimmedStart, end: trimmedEnd } } lineStart = cursor + 1 }