TestEmptyReplyNudgeFiresOnceThenSurfaces: if the model stays empty even after the re-prompt (e.g. a server that deterministically swallows the call), the latch must stop at one retry (no infinite loop) and the failure must be surfaced rather than dying silently as before.
(t *testing.T)
| 3286 | w.Header().Set("Content-Type", "text/event-stream") |
| 3287 | round++ |
| 3288 | if round == 1 { |
| 3289 | // Empty assistant message: stop with no content delta, no tool calls. |
| 3290 | fmt.Fprintf(w, "data: %s\n\n", `{"type":"response.completed","response":{"usage":{"output_tokens":1}}}`) |
| 3291 | return |
| 3292 | } |
| 3293 | fmt.Fprintf(w, "data: %s\n\n", `{"type":"response.output_text.delta","delta":"fixed and verified"}`) |
| 3294 | fmt.Fprintf(w, "data: %s\n\n", `{"type":"response.completed","response":{"usage":{"output_tokens":3}}}`) |
| 3295 | } |
| 3296 | |
| 3297 | m := newTestModel(t, handler) |
| 3298 | final := drainFinal(t, m, "build it") |
| 3299 | |
| 3300 | if round != 2 { |
| 3301 | t.Fatalf("empty reply must trigger exactly one re-prompt (want 2 requests, got %d)", round) |
| 3302 | } |
| 3303 | var sawNudge bool |
| 3304 | for _, msg := range final.history { |
| 3305 | if msg.Role == chmctx.RoleSystem && strings.Contains(msg.Content, "no reply and no tool call") { |
| 3306 | sawNudge = true |
| 3307 | } |
| 3308 | } |
| 3309 | if !sawNudge { |
| 3310 | t.Fatalf("expected an empty-reply system nudge in history; got %+v", final.history) |
| 3311 | } |
| 3312 | scroll := stripANSI(final.scroll.String()) |
| 3313 | if !strings.Contains(scroll, "fixed and verified") { |
nothing calls this directly
no test coverage detected