Skip to content

feat: inject rejected-tool feedback as user message (#96)#102

Merged
VforVitorio merged 4 commits intodevfrom
feat/extended-interactive-prompt
Apr 7, 2026
Merged

feat: inject rejected-tool feedback as user message (#96)#102
VforVitorio merged 4 commits intodevfrom
feat/extended-interactive-prompt

Conversation

@VforVitorio
Copy link
Copy Markdown
Owner

Summary

Finishes the last missing piece of #96 (extended interactive prompt).

The arrow-key approval menu in ask mode already offered three options
(Yes, No / Tell lmcode what to do instead, Always) thanks to
PR #95, but when the user typed a redirect instruction after choosing
No, the text was returned inline as a tool error string. That made
the model treat the user's words as tool output and the context felt
off.

This PR routes the feedback through Agent._pending_user_feedback and
replays it as a real user turn on the next iteration of the chat loop.

Changes

  • Agent.__init__: new _pending_user_feedback: str | None slot.
  • _wrap_tool: when the user types redirect text, stash it and return
    a generic Tool execution cancelled by user error so the model
    stops retrying and waits.
  • run(): new auto_input variable. When set, the next loop iteration
    skips session.prompt_async and replays the feedback as if the user
    had typed it at the prompt (complete with a dim › <text> row so the
    injection is visible).
  • The interrupted path clears _pending_user_feedback so Ctrl+C cannot
    leak a stale redirect into the next turn.
  • CLAUDE.md: documents ui/_interactive_prompt.py in the module map
    and key files table.

Resulting history flow

```
user: write to /x/y.py
assistant: [tool_call write_file]
tool: error: Tool execution cancelled by user. Do not retry...
assistant: ok, cancelled. Waiting for your new instructions.
user: write it to /x/z.py instead ← injected as a real user turn
assistant: [tool_call write_file with new path]
```

Test plan

  • `uv run ruff check .`
  • `uv run ruff format --check .`
  • `uv run mypy src/`
  • `uv run pytest` (199 passed)
  • Manual: in ask mode, ask for a write_file, pick No / Tell lmcode what to do instead, type a redirect, verify it appears as a new user turn and the model acts on it.

Closes #96.

When the user selects "No / Tell lmcode what to do instead" in the
interactive approval prompt and types a redirect, the feedback is now
stashed in ``Agent._pending_user_feedback`` and injected as a real
``user`` message on the next loop iteration, instead of being returned
inline as a tool error string.

``run()`` gains an ``auto_input`` slot that, when set, skips
``session.prompt_async`` and replays the feedback as if the user had
just typed it. The interrupted path clears any pending feedback so a
stale redirect cannot leak across Ctrl+C.

Closes #96.
Adds the `ui/_interactive_prompt.py` file to the module map and key
files table, and reformats tables/sections for consistency.
@VforVitorio VforVitorio merged commit 29a0820 into dev Apr 7, 2026
6 checks passed
@VforVitorio VforVitorio deleted the feat/extended-interactive-prompt branch April 7, 2026 07:54
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