Repository navigation
Conversation
Signed-off-by: Muhammad Rizky Rizaldi <myquinn489@gmail.com>
oleg68
left a comment
There was a problem hiding this comment.
Detector change looks good: gating the extra lines on the ⏸/⏵ glyph keeps menu text from being mistaken for the footer, and the negative test covers that. Two requested changes inline (stuck state on unchecked exception, flaky test). Also optional: sendShiftTab() (manual single Shift+Tab) still sets modeSwitchInProgress = false in its finally and can clear the flag while the worker is running; and please check the pom.xml version bump against current main after rebase.
| target = editModeSwitchTarget; | ||
| } | ||
| } | ||
| } catch (IOException | InterruptedException ex) { |
There was a problem hiding this comment.
Thanks for the fix, the single-worker retargeting is the right design.
One robustness issue: the old finally { modeSwitchInProgress = false; } was removed, and this catch only handles IOException | InterruptedException. If sendOneShiftTab() throws an unchecked exception (e.g. an NPE because connector became null when the session was stopped mid-switch), editModeSwitchTarget stays non-null forever. After that every sendShiftTabsUntilMode call just "retargets" and returns (no worker ever runs again), and modeSwitchInProgress stays true, so the screen→model mode sync in the poll loop is disabled for the rest of the session.
Catching RuntimeException here reuses the existing cleanup block. (I'd avoid moving the cleanup into finally: on a normal exit it could clobber the target of a new worker started right after the loop ended.)
| } catch (IOException | InterruptedException ex) { | |
| } catch (IOException | InterruptedException | RuntimeException ex) { |
| setModeSwitchPollMs(c, 1); | ||
|
|
||
| c.onEditModeComboChanged(EditMode.AUTO); | ||
| c.onEditModeComboChanged(EditMode.PLAN); |
There was a problem hiding this comment.
This test can be flaky: it assumes the second request arrives while worker 1 is still running, which only holds because the fake poll interval is 1 ms and the request follows immediately. On a loaded CI machine worker 1 may finish first, then a second thread is started and senders.size() is 2.
Make it deterministic by blocking the first Shift+Tab until the second request has been issued, e.g.:
java.util.concurrent.CountDownLatch secondIssued = new java.util.concurrent.CountDownLatch(1);
// in the overridden sendOneShiftTab():
senders.add(Thread.currentThread());
try { secondIssued.await(2, java.util.concurrent.TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
ccMode.updateAndGet(i -> (i + 1) % cycle.length);
// in the test body:
c.onEditModeComboChanged(EditMode.AUTO);
c.onEditModeComboChanged(EditMode.PLAN);
secondIssued.countDown();| pass | ||
|
|
||
|
|
||
| def dump(term, label): |
There was a problem hiding this comment.
Minor / optional: claude-launch-tests/test_edit_mode_footer.py is a capture script without assertions. shutil.which('claude') returns None when Claude is not on PATH, which then fails with a confusing error inside subprocess.Popen; consider an explicit sys.exit('claude not found on PATH').
Supersedes #193 (rebased onto current `main`, review comments addressed). Original work by @Rizky92 — their commit is kept with authorship. ## Problem - Claude Code 2.1.x renders `● high · /effort` below the mode footer line, so the mode was never detected when idle and the combo jumped to "Ask on Edit". - A second mode request during a running switch started a second Shift+Tab worker, and the two cycled endlessly. ## Fix - `ScreenContentDetector.detectEditMode`: after the bottom-most line, falls back to the 2 lines above, only if they start with `⏸`/`⏵`. Old layouts are checked first, with unchanged rules. - `ClaudeSessionController`: single worker with a retargetable `editModeSwitchTarget`. ## Review fixes (on top of the original commit) - Worker also catches `RuntimeException`, so the in-progress flag is never stuck (new test). - Retarget test made deterministic with a `CountDownLatch`. - `sendShiftTab()` no longer clears `modeSwitchInProgress` while a worker owns it. - Capture script exits with a clear message if `claude` is not on PATH. `mvn package`: 1140 tests, 0 failures. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Muhammad Rizky Rizaldi <myquinn489@gmail.com> Co-authored-by: Muhammad Rizky Rizaldi <myquinn489@gmail.com> Co-authored-by: Oleg Samarin <osamarin@openintegration.inc> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Replaced with #195 |
This PR attempt a fix to mode selector. Per claude code v2.1.301, the mode selector would change mid-prompt. This was caused by a visual change to claude code's status bar, unable to recognize the current mode.