toolCallLeakWarning returns a user-facing diagnostic when the newest assistant message carries a tool-call opener (` `) in its text instead of structured tool_calls, the dominant local-hosting failure: a misconfigured/missing server parser leaks the call as content with finish_reason "stop
(history []chmctx.Message)
| 1031 | func newestAssistantEmpty(history []chmctx.Message) bool { |
| 1032 | msg, ok := newestAssistant(history) |
| 1033 | return ok && strings.TrimSpace(msg.Content) == "" && len(msg.ToolCalls) == 0 |
| 1034 | } |
| 1035 | |
| 1036 | // newestAssistantUnverified reports whether the turn's final assistant message |
| 1037 | // already carries an "unverified" marker, the honest self-assessment the finish |
| 1038 | // nudge exists to elicit. Case-insensitive: the model writes "unverified" / |
| 1039 | // "Unverified" interchangeably. Used to suppress the finish nudge on a finish |
| 1040 | // that already named what it couldn't prove (see maybeVerifyNudge). |
| 1041 | func newestAssistantUnverified(history []chmctx.Message) bool { |
| 1042 | msg, ok := newestAssistant(history) |
| 1043 | return ok && strings.Contains(strings.ToLower(msg.Content), "unverified") |
| 1044 | } |
| 1045 | |
| 1046 | // toolCallLeakWarning returns a user-facing diagnostic when the newest assistant |
| 1047 | // message carries a tool-call opener (`<tool_call>`) in its text instead of |
| 1048 | // structured tool_calls, the dominant local-hosting failure: a |
| 1049 | // misconfigured/missing server parser leaks the call as content with |
| 1050 | // finish_reason "stop", so the turn ends silently with the tool intent stranded. |
no outgoing calls