Skip to content

Commit 30a8ede

Browse files
committed
fix(agent): do not treat empty OnText as committed answer prose
CodeRabbit nit on #976: OnText("") was setting forwardedVisibleText and blocking an eligible mid-stream abort retry even though collected.Text stayed empty. Only non-empty text counts as forwarded visible prose.
1 parent 2f6a35a commit 30a8ede

2 files changed

Lines changed: 16 additions & 10 deletions

File tree

‎internal/agent/loop.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,11 @@ func Run(ctx context.Context, prompt string, provider Provider, options Options)
378378
rec.StampFirstToken()
379379
}
380380
if onText != nil {
381-
forwardedVisibleText = true
381+
// Zero-length chunks are not committed answer prose; counting
382+
// them would block an eligible mid-stream abort retry.
383+
if s != "" {
384+
forwardedVisibleText = true
385+
}
382386
onText(s)
383387
}
384388
}

‎internal/agent/midstream_retry_test.go‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,20 +137,22 @@ func TestRunDoesNotRetryMidStreamAbortAfterPartialOutput(t *testing.T) {
137137
}
138138
}
139139

140-
// Empty StreamEventText still invokes OnText, so forwardedVisibleText is true
141-
// while collected.Text stays empty. Neutralising !forwardedVisibleText in the
142-
// gate would retry this; collected.Text == "" would not catch it.
143-
func TestRunDoesNotRetryMidStreamAbortAfterForwardedEmptyText(t *testing.T) {
140+
// A zero-length OnText chunk is not committed answer prose, so an eligible
141+
// transport abort still retries.
142+
func TestRunRetriesMidStreamAbortAfterEmptyTextEvent(t *testing.T) {
144143
p := &midStreamAbortProvider{abortBefore: 1, emptyTextEvent: true}
145-
_, err := Run(context.Background(), "go", p, Options{
144+
result, err := Run(context.Background(), "go", p, Options{
146145
Registry: tools.NewRegistry(),
147146
OnText: func(string) {},
148147
})
149-
if err == nil {
150-
t.Fatal("forwarded visible text (even empty chunk) must block retry")
148+
if err != nil {
149+
t.Fatalf("empty OnText must not block mid-stream abort retry, got %v", err)
151150
}
152-
if got := atomic.LoadInt32(&p.calls); got != 1 {
153-
t.Fatalf("forwardedVisibleText must block retry, got %d calls", got)
151+
if result.FinalAnswer != "done" {
152+
t.Fatalf("final answer = %q, want %q", result.FinalAnswer, "done")
153+
}
154+
if got := atomic.LoadInt32(&p.calls); got != 2 {
155+
t.Fatalf("want 2 calls (1 abort + 1 retry), got %d", got)
154156
}
155157
}
156158

0 commit comments

Comments
 (0)