Skip to content

# Add agent-shell-quote-reply and DWIM context prefill for queue-compose#12

Draft
timvisher-dd wants to merge 4 commits into
mainfrom
quote-reply
Draft

# Add agent-shell-quote-reply and DWIM context prefill for queue-compose#12
timvisher-dd wants to merge 4 commits into
mainfrom
quote-reply

Conversation

@timvisher-dd

Copy link
Copy Markdown
Owner

Summary

Two related compose-buffer enhancements:

  • agent-shell-quote-reply (new) pops the queue-compose buffer
    prefilled with the agent's last prose reply, wrapped as a GFM
    block quote. Bound to q in the agent-shell-help-menu
    "Insert" group.
  • agent-shell-queue-request, when called interactively without
    a prompt, now gathers any DWIM context available in the source
    buffer (active region, error at point, dired marked files) and
    prefills the compose buffer with it. Regions from buffers with
    no file association are wrapped as GFM block quotes; file-
    visiting and dired context keep their existing purpose-built
    decoration.

Why not just use shell-maker--command-and-response-at-point?

It returns the entire rendered turn span — shell-maker--extract- history' takes a buffer-substring' between
`' and the next prompt, so tool-call
drawers and thought blocks are included. For a quote-reply that's
not what you want.

agent-shell--last-agent-message-text' walks back from point-max' to the most recent fragment whose
agent-shell-ui-state' qualified-id ends in -agent_message_chunk' and pulls the raw body from
`agent-shell-ui--content-store'. Tool-call and thought fragments
are skipped by the suffix check.

`text-property-search-backward' gotcha

When its predicate rejects the nearest match, it returns nil
rather than continuing the walk. The first implementation used
the built-in predicate path and silently returned nil whenever a
tool-call fragment sat between point-max and the agent message.
The fix loops over property changes manually and applies the
suffix check each step — the regression test
(`agent-shell--last-agent-message-text-skips-tool-calls') fails
without the loop.

Test plan

  • 13 new ERT tests in tests/agent-shell-tests.el:
    • `agent-shell--gfm-blockquote' (single-line, multiline,
      nested code fence, already-quoted input)
    • `agent-shell--last-agent-message-text' (returns body,
      skips tool calls, picks last of many, nil when empty)
    • `agent-shell-quote-reply' (error outside shell, error when
      no reply, pops compose with quoted reply)
    • agent-shell-queue-compose-pop' :initial-content' (insert
      into fresh buffer, append to existing draft with blank-line
      separator, no-op when omitted)
    • agent-shell--compose-initial-content' (quotes non-file region, delegates to --context' otherwise)
    • Updated agent-shell-queue-request-without-prompt-pops- compose' for the new &key' signature.
  • Full bin/test: 259/260 passing, 1 pre-existing skip,
    all CI checks green.
  • Live-validate: not yet run (1Password CLI not signed in
    when prepping the PR). Worth a manual run that produces a
    reply with tool calls in the same turn, then exercising
    `agent-shell-quote-reply' to confirm the quoted output
    contains only the prose.

Refs

  • agent-shell-wafa

timvisher-dd and others added 4 commits May 23, 2026 17:27
`agent-shell-quote-reply' pops the queue-compose buffer prefilled with
the agent's last prose reply wrapped as a GFM block quote, and
`agent-shell-queue-request' now gathers any DWIM context available in
the source buffer (active region, error at point, dired marked files)
and prefills the compose buffer with it.  Regions from buffers with no
file association are wrapped as GFM block quotes; file-visiting and
dired context keep their existing purpose-built decoration.

Cannot use `shell-maker--command-and-response-at-point' to find the
last reply because `shell-maker--extract-history' returns the entire
rendered turn span, including tool-call drawers and thought blocks.
`agent-shell--last-agent-message-text' walks back to the most recent
`agent_message_chunk' fragment and pulls the raw body from
`agent-shell-ui--content-store' instead.

`text-property-search-backward' returns nil when its predicate rejects
the nearest match rather than continuing the walk, so the implementation
loops over property changes and applies the suffix check manually —
otherwise a tool-call fragment between point-max and the agent message
silently swallows the result.

Bound to `q' in the `agent-shell-help-menu' "Insert" group.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
agent-shell--insert-to-shell-buffer parked point at the start of the
inserted text — the DWIM "land on your context" behavior — for every
insertion, including the :submit t path used by
agent-shell--process-pending-request and interactive C-c C-c on a
queued request. After submit, that text becomes transcript above the
new prompt, so point was left at the end of the last agent message.
shell-maker only auto-scrolls streamed output while point is at
point-max, so the cursor stayed stranded above the prompt for the
whole turn.

Leave point at point-max on the submit path so it tracks the prompt;
keep the start-of-context placement only for non-submit insertions.
Add a regression test asserting point is at end-of-buffer when
shell-maker-submit fires (fails without the fix).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The interactive submit path (typing at the shell prompt and pressing
RET) stranded point above the streamed reply for the whole turn.
shell-maker-submit skips its own goto-char when
shell-maker-point-at-last-prompt-p is true, so after comint-send-input
point sits at the response boundary just below the echoed input — not
at point-max. The new prompt and the streamed reply land below point,
and shell-maker only auto-scrolls while point is at end-of-buffer, so
the cursor stayed above the reply until the turn finished.

3ac141c fixed only the programmatic :submit t path (goto point-max
before shell-maker-submit); the interactive RET path was never covered.
The bug reproduces with or without agent-shell--with-preserved-point,
so fix it at the submission entry point: agent-shell--handle (the
:execute-command callback) now snaps point to point-max whenever a
command is submitted, so the cursor follows streaming output down to
the new prompt. A user who scrolls up mid-stream is still honored.

Verified live against a real Claude turn: without the fix point sat 4
lines above point-max after the turn; with it point lands at point-max.
Add two regression tests asserting agent-shell--handle moves point to
point-max for a real command and leaves it alone for a nil (bootstrap)
command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lected

The queue-compose C-c C-c path submits with :no-focus t, so the shell
window is never selected. The submit-time point fixes (3ac141c, 531fcc4)
moved only buffer point via goto-char, which does not update the
window-point of a non-selected window. The shell window therefore kept
the position the user had parked point at before invoking
agent-shell-queue-request, and the visible cursor snapped back there for
the whole turn. with-preserved-point cannot cover this — it manages
buffer point only.

agent-shell--handle now also pushes window-point to point-max for every
window showing the shell, mirroring the set-window-point pattern in
agent-shell-jump-to-latest-permission-button-row. Add a regression test
that displays the shell in an unselected window, parks its window-point
above the prompt, and asserts submit moves window-point to point-max
(fails without the fix).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant