fix(agent): don't attach a pre-API steer to a prior turn's tool result (#107272) - #107284
PRATHAMESH75 wants to merge 1 commit into
Conversation
NousResearch#107272) A /steer accepted on a turn's first iteration — e.g. typed while an attached image is still preprocessing, before the first API call — was drained pre-API and injected after the newest `role=="tool"` message anywhere in the list. When the session already holds a prior-turn tool result, that message sits BEFORE the current user prompt, so the steer landed in already-persisted history ahead of the current turn and was silently ignored: the CLI acknowledged "arrives after the next tool call" but the turn never applied it. `_inject_steer_after_newest_tool_result` now stops the backward scan at the current user row: the newest tool message only counts when it belongs to the current turn (after the last user row). Otherwise the steer is re-queued, so the turn finalizer surfaces it as the next turn (the CLI already delivers `result["pending_steer"]` as the next prompt) instead of losing it — matching the issue's expected behavior. Mid-turn steering between tool iterations is unchanged, since there the current-turn tool result is the newest message.
Duplicate of #107274, which landed first and fixes the same |
|
Closing in favour of #107274 by @KoNit-K, opened ~7 min earlier with an equivalent |
What
In the classic CLI, a
/steertyped while an attached image is still being preprocessed — before the turn's first API call — is acknowledged ("⏩ Steer queued — arrives after the next tool call") but the turn completes without applying it, and nothing indicates it was dropped (#107272).Root cause
The steer is accepted into
_pending_steer, then drained pre-API inturn_iteration_prepand handed to_inject_steer_after_newest_tool_result, which walks the message list backward and inserts the steer after the newestrole == "tool"message. That helper is written for mid-turn steering (between tool-call iterations), where the newest tool result belongs to the current turn.On a turn's first iteration, there is no current-turn tool result yet. If the session already contains a prior turn's tool result (the issue's repro: "a session that already contains at least one tool result"), that stale tool message sits before the current user prompt. The steer is therefore inserted into already-persisted history, ahead of the current turn — exactly the "attached to an earlier turn" case the issue calls out — and the model ignores it as old context.
Fix
_inject_steer_after_newest_tool_resultnow stops the backward scan at the current user row. A tool message only counts as an injection target when it's newer than the last user row (i.e. part of the current turn). Otherwise the steer is re-queued via_requeue_pending_steer, so:result["pending_steer"](existing path), and⏩ Delivering leftover /steer as next turn(existing path,cli_chat_turn_mixin.py) — visible, correctly ordered, not lost.This matches the issue's Expected Behavior ("queue it without attaching it to an earlier turn"). Mid-turn steering is unchanged: there the current-turn tool result is the newest message, so it's found before any user row.
Tests
tests/run_agent/test_steer.py::TestPreApiCallSteerDrain:test_pre_api_drain_restashes_when_newest_tool_is_from_a_prior_turn— first-iteration steer with a prior-turn tool result before the current user prompt: history is untouched and the steer is re-queued into_pending_steer.test_pre_api_drain_appends_user_row_and_leaves_tool_row_untouched(mid-turn) andtest_pre_api_drain_restashes_when_no_tool_messagestill pass.Full file: 38 passed.
ruff checkclean.Fixes #107272