ResolveChainMode scans DB messages from the end to inspect the current trailing user turn and detect whether the immediately preceding assistant/tool block can chain from a provider response ID.
(messages []database.ChatMessage)
| 204 | // trailing user turn and detect whether the immediately preceding assistant/tool |
| 205 | // block can chain from a provider response ID. |
| 206 | func ResolveChainMode(messages []database.ChatMessage) ChainModeInfo { |
| 207 | var info ChainModeInfo |
| 208 | i := len(messages) - 1 |
| 209 | for ; i >= 0; i-- { |
| 210 | if messages[i].Role != database.ChatMessageRoleUser { |
| 211 | break |
| 212 | } |
| 213 | if userMessageContributesToChainMode(messages[i]) { |
| 214 | info.contributingTrailingUserCount++ |
| 215 | } |
| 216 | } |
| 217 | for ; i >= 0; i-- { |
| 218 | switch messages[i].Role { |
| 219 | case database.ChatMessageRoleAssistant: |
| 220 | if messages[i].ProviderResponseID.Valid && |
| 221 | messages[i].ProviderResponseID.String != "" { |
| 222 | info.previousResponseID = messages[i].ProviderResponseID.String |
| 223 | if messages[i].ModelConfigID.Valid { |
| 224 | info.modelConfigID = messages[i].ModelConfigID.UUID |
| 225 | } |
| 226 | info.hasUnresolvedLocalToolCalls = assistantHasUnresolvedLocalToolCalls(messages, i) |
| 227 | if !info.hasUnresolvedLocalToolCalls { |
| 228 | info.providerMissingToolResults = providerHasMissingToolResults(messages, i) |
| 229 | } |
| 230 | return info |
| 231 | } |
| 232 | return info |
| 233 | case database.ChatMessageRoleTool: |
| 234 | continue |
| 235 | default: |
| 236 | return info |
| 237 | } |
| 238 | } |
| 239 | return info |
| 240 | } |
| 241 | |
| 242 | // FilterPromptForChainMode keeps only system messages and the trailing user |
| 243 | // messages that still contribute model-visible content to the current turn. |