fix(agent): defer run-loop publish to after all steering continuations

Before this fix the Run loop published the initial response immediately,
before draining queued steering messages. This caused two outbound
messages when a late steering message arrived (initial + continued),
whereas upstream only ever emits one final message.

Additionally, the handleReasoning goroutine was launched with turnCtx,
which is canceled by defer turnCancel() as soon as runTurn returns.
Removal of the eager-save block at the end of runTurn made it return
faster, exposing a pre-existing race where the goroutine checked
ctx.Err() and returned without publishing. Fixed by using the
longer-lived parent ctx.

Both issues were caught by the two new tests added in the previous
commit (TestOnDelivered_* and TestContinueResponse_*).
This commit is contained in:
Dmitrii Balabanov 2026-03-31 17:12:57 +03:00
parent 6ea3ce6aa0
commit 9880cb343b

View file

@ -574,11 +574,12 @@ func (al *AgentLoop) Run(ctx context.Context) error {
return return
} }
if response.Content != "" { // Accumulate the final response before publishing so that a
al.publishAgentResponseIfNeeded(ctx, response, target.Channel, target.ChatID) // steering continuation can supersede the initial reply.
} // We publish exactly once at the end (matching upstream behavior).
finalResponse := response
prevContent := response.Content prevContent := response.Content
for al.pendingSteeringCountForScope(target.SessionKey) > 0 { for al.pendingSteeringCountForScope(target.SessionKey) > 0 {
logger.InfoCF("agent", "Continuing queued steering after turn end", logger.InfoCF("agent", "Continuing queued steering after turn end",
map[string]any{ map[string]any{
@ -607,7 +608,7 @@ func (al *AgentLoop) Run(ctx context.Context) error {
if continued.Content == "" { if continued.Content == "" {
return return
} }
al.publishAgentResponseIfNeeded(ctx, continued, target.Channel, target.ChatID) finalResponse = continued
prevContent = continued.Content prevContent = continued.Content
} }
@ -641,9 +642,13 @@ func (al *AgentLoop) Run(ctx context.Context) error {
if continued.Content == "" { if continued.Content == "" {
break break
} }
al.publishAgentResponseIfNeeded(ctx, continued, target.Channel, target.ChatID) finalResponse = continued
prevContent = continued.Content prevContent = continued.Content
} }
if finalResponse.Content != "" {
al.publishAgentResponseIfNeeded(ctx, finalResponse, target.Channel, target.ChatID)
}
}() }()
} }
} }