newestAssistantUnverified reports whether the turn's final assistant message already carries an "unverified" marker, the honest self-assessment the finish nudge exists to elicit. Case-insensitive: the model writes "unverified" / "Unverified" interchangeably. Used to suppress the finish nudge on a fi
(history []chmctx.Message)
| 1008 | m.emptyNudged = true |
| 1009 | dbgWritef("nudge", "empty reply nudge injected (turn ended with no content and no tool call)") |
| 1010 | m.history = append(m.history, chmctx.Message{ |
| 1011 | Role: chmctx.RoleSystem, |
| 1012 | Content: nudgeOrigin + "Your last turn ended with no reply and no tool call. If you meant to call a tool and it did not run, issue it again now as a proper tool call. If you are still working, continue. If the task is done, check it against the original request: actually run or drive what proves it works: then reply with a one line summary.", |
| 1013 | }) |
| 1014 | m.phase = phaseThinking |
| 1015 | return m, m.startChat() |
| 1016 | } |
| 1017 | m.appendLine(styleError.Render("⚠ the model ended its turn with no reply and no tool call: it stalled, or your server dropped the call. If thinking is on, its reasoning parser may be swallowing calls: enable one (e.g. vLLM `--reasoning-parser`) or disable thinking for tool turns.")) |
| 1018 | dbgWritef("leak", "turn ended with an empty assistant message after a reprompt (model stalled or the call was swallowed server side)") |
| 1019 | outcome = outcomeStopped |
| 1020 | } else if w := toolCallLeakWarning(m.history); w != "" { |
| 1021 | // The model meant to call a tool but its server's parser leaked the raw |