fix(steer): drain /steer between individual tool calls, not at batch end (#12959)

Previously, /steer text was only injected after an entire tool batch
completed (_execute_tool_calls_sequential/concurrent returned). If the
batch had a long-running tool (delegate_task, terminal build), the
steer waited for ALL tools to finish before landing — functionally
identical to /queue from the user's perspective.

Now _apply_pending_steer_to_tool_results() is called after EACH
individual tool result is appended to messages, in both the sequential
and concurrent paths. A steer arriving during Tool 1 lands in Tool 1's
result before Tool 2 starts executing.

Also handles leftover steers in the gateway: if a steer arrives during
the final API call (no tool batch to drain into), it's now delivered as
the next user turn instead of being silently dropped.

Fixes user report from Utku.
This commit is contained in:
Teknium 2026-04-20 03:08:04 -07:00 committed by GitHub
parent 22efc81cd7
commit eba7c869bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 0 deletions

View file

@ -8404,6 +8404,11 @@ class AIAgent:
}
messages.append(tool_msg)
# ── Per-tool /steer drain ───────────────────────────────────
# Same as the sequential path: drain between each collected
# result so the steer lands as early as possible.
self._apply_pending_steer_to_tool_results(messages, 1)
# ── Per-turn aggregate budget enforcement ─────────────────────────
num_tools = len(parsed_calls)
if num_tools > 0:
@ -8767,6 +8772,12 @@ class AIAgent:
}
messages.append(tool_msg)
# ── Per-tool /steer drain ───────────────────────────────────
# Drain pending steer BETWEEN individual tool calls so the
# injection lands as soon as a tool finishes — not after the
# entire batch. The model sees it on the next API iteration.
self._apply_pending_steer_to_tool_results(messages, 1)
if not self.quiet_mode:
if self.verbose_logging:
print(f" ✅ Tool {i} completed in {tool_duration:.2f}s")