Restore point when no prompt is found - #43
Open
OSadovy wants to merge 1 commit into
Open
Conversation
shell-maker--re-search-forward-prompt walks past prompt lookalikes in response text, rejecting those without the comint-highlight-prompt face. When none of them is a real prompt it returns nil, but leaves point on the last one searched rather than where it started. shell-maker-narrow-to-prompt discards the return value and instead asks whether point moved, so a leaked point makes it end the current interaction at a lookalike. Everything after that falls outside, and callers such as shell-maker--command-and-response-at-point see a truncated response. This only bites while a shell is still busy: once a new prompt is printed the search finds it and point never leaks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
I use agent-shell. Claude was in plan mode: it wrote a long plan into the shell
buffer and stopped for approval. The plan was plainly there in the shell buffer,
but agent-shell's viewport - which re-derives the current interaction through
shell-maker--command-and-response-at-point- showed the response cut off longbefore the plan, ending part-way through an earlier tool call.
Earlier in that session the agent had read agent-shell's own source into the
transcript, so the buffer contained the literal text
:shell-prompt "Claude> ".That is what triggered it, but the lookalike text isn't the bug:
shell-maker--re-search-forward-promptcorrectly rejected all four occurrences.Cause
shell-maker--re-search-forward-promptloopsre-search-forward, moving pointonto each candidate and rejecting those without the
comint-highlight-promptface. When it runs out of candidates it returns nil - but point is left on the
last rejected match instead of where it started.
shell-maker-narrow-to-promptdiscards the return value and reads point instead:"Did I move?" is a reasonable way to ask whether there was a next prompt, but it
only holds if a failed search leaves point alone. In my buffer point had been
dragged ~240k characters forward, so
--prompt-begin-positionanswered with alookalike and narrowing stopped there. Everything past it - the entire plan -
fell outside the interaction.
The trailing prompt is why this isn't seen more often: after a finished exchange
there is a real prompt at the end, the search finds it, and nothing leaks. It
only goes wrong while the shell is still busy - which is exactly when a plan is
on screen waiting to be answered.
Fix
Restore point when nothing is found, the way
re-search-forwarditself does.The other two callers,
shell-maker-history-positionandshell-maker--extract-history, run inside their ownsave-excursionand don'tread point after a nil return, so they are unaffected.
Reproducing
Anchored regexp, no agent-shell, no real session data:
Before:
"Here is a transcript excerpt:"- the response stops at the lookalike.After: the full three lines.
Note the regexp is anchored, so this is not about unanchored prompt regexps.
(agent-shell does pass unanchored ones)
Test
shell-maker-history-test-search-prompt-leaves-point-when-not-found, added nextto the existing
-extract-preserves-point. Fails before the change, passesafter, and the other 14 in that file still pass.
What else I considered
shell-maker--prompt-begin-positionsearches backward with a plainre-search-backward comint-prompt-regexpand no face check, so it can stillanchor on a lookalike sitting between the real prompt and point. Guarding it
would independently have saved me here, but it decides where interactions begin
for
shell-maker-delete-interaction-at-pointtoo, and it needs a "foundnothing" case designed. I'd rather get package author's call on it.