diff --git a/CHANGELOG.md b/CHANGELOG.md index 51005576..9319dc6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,4 @@ +- Fixed an unnumbered choice prompt (e.g. the "trust this folder" dialog) showing every line of the surrounding text as a bogus selectable option instead of just the real choices, and losing the "Yes" option entirely by merging it into the "No" option's description - Fixed ChatGPT Subscription token refresh hanging indefinitely (freezing the session) when a profile's custom HTTPS/HTTP proxy hostname was slow or unreachable to resolve via DNS - Fixed a choice-dialog prompt (e.g. a Bash-command permission prompt) flickering and repeatedly resizing when Claude's response text re-wrapped to a slightly different width after the dialog first appeared diff --git a/pom.xml b/pom.xml index 98a0e36c..cf0d2edd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.nbplugins netbeans-plugin-claude-code-gui - 1.3.33-SNAPSHOT + 1.3.34-SNAPSHOT nbm Netbeans Plugin Claude Code GUI NetBeans plugin that provides a GUI for Claude Code CLI — run claude code sessions directly inside the IDE. diff --git a/src/main/java/io/github/nbplugins/claudecodegui/process/ScreenContentDetector.java b/src/main/java/io/github/nbplugins/claudecodegui/process/ScreenContentDetector.java index 658a8ca0..0b078d99 100644 --- a/src/main/java/io/github/nbplugins/claudecodegui/process/ScreenContentDetector.java +++ b/src/main/java/io/github/nbplugins/claudecodegui/process/ScreenContentDetector.java @@ -330,10 +330,20 @@ Optional detectUnnumberedChoiceMenu(List screenLines) { int stopRow = -1; // row where we stopped (first non-option line above options) int i = footerRow - 1; + boolean firstBlock = true; while (i >= 0) { - // Skip blank lines between blocks - while (i >= 0 && screenLines.get(i).isBlank()) i--; - if (i < 0) break; + if (screenLines.get(i).isBlank()) { + if (!firstBlock) { + // A blank line after at least one option block was already collected marks + // the end of the option list (real menu items are never blank-separated from + // each other) — stop here instead of skipping through unrelated prose above. + stopRow = i; + break; + } + // Allow a single blank gap between the footer and the first (bottom-most) option. + while (i >= 0 && screenLines.get(i).isBlank()) i--; + if (i < 0) break; + } String raw = screenLines.get(i); String trimmed = raw.trim(); @@ -360,12 +370,16 @@ Optional detectUnnumberedChoiceMenu(List screenLines) { break; } - // Collect this block: desc = current line, main = line above (if non-blank) + // Collect this block: desc = current line, main = line above (if non-blank). + // Only pair the two lines when the lower one carries the metadata separator "·" + // (e.g. "23 hours ago · bugfix/new-kafka · 1MB") — the shape real 2-line unnumbered + // entries use. Without that marker, treat the line as its own single-line option so + // two genuinely separate options (e.g. "No, exit" / "Yes, I trust this folder") don't + // get fused into one. String desc = trimmed; - i--; String main = null; - if (i >= 0 && !screenLines.get(i).isBlank()) { - String raw2 = screenLines.get(i); + if (desc.indexOf('·') >= 0 && i - 1 >= 0 && !screenLines.get(i - 1).isBlank()) { + String raw2 = screenLines.get(i - 1); String trimmed2 = raw2.trim(); if (!isSeparatorLine(trimmed2) && !OPTION_LINE.matcher(trimmed2).matches() && !isBoxDrawingLine(trimmed2) && !trimmed2.contains("\u2315") @@ -374,6 +388,7 @@ Optional detectUnnumberedChoiceMenu(List screenLines) { i--; } } + i--; if (main == null) { // Single-line block — treat as main with no description main = desc; @@ -381,6 +396,7 @@ Optional detectUnnumberedChoiceMenu(List screenLines) { } blockMainLines.add(0, main); blockDescLines.add(0, desc); + firstBlock = false; } if (blockMainLines.size() < 2) return Optional.empty(); diff --git a/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.expectedRes.json b/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.expectedRes.json new file mode 100644 index 00000000..c2d19aef --- /dev/null +++ b/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.expectedRes.json @@ -0,0 +1,8 @@ +{ + "text": "Security guide", + "options": [ + {"display": "No, exit", "response": "ARROW:0"}, + {"display": "Yes, I trust this folder", "response": "ARROW:1"} + ], + "defaultOptionIndex": 0 +} diff --git a/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.src.txt b/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.src.txt new file mode 100644 index 00000000..fdd88c0a --- /dev/null +++ b/src/test/resources/io/github/nbplugins/claudecodegui/process/screen-content-detector/detect-choice-menu/trust-folder-prompt.src.txt @@ -0,0 +1,21 @@ +───────────────────────────────────────────────────────────────────────────────────────────────────────── + Accessing workspace: + + /home/oleg/git/sigma/SigmaOperationStorage + + Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known + open source project, or work from your team). If not, take a moment to review what's in this folder + first. + + Claude Code'll be able to read, edit, and execute files here. + + ⚠ This folder pre-approves 2 tool permissions in .claude/settings.local.json: + mcp__netbeans__show_markdown and mcp__netbeans__show_markdown_file + These will apply without asking. Only proceed if you trust this configuration. + + Security guide + + ❯ No, exit + Yes, I trust this folder + + Enter to confirm · Esc to cancel