(messages []map[string]any)
| 255 | } |
| 256 | |
| 257 | func EnforceImmediateToolResults(messages []map[string]any) []map[string]any { |
| 258 | working := copyMessages(messages) |
| 259 | out := make([]map[string]any, 0, len(working)) |
| 260 | for i := 0; i < len(working); i++ { |
| 261 | msg := working[i] |
| 262 | if msg == nil { |
| 263 | continue |
| 264 | } |
| 265 | if len(contentBlocks(msg["content"])) == 0 { |
| 266 | continue |
| 267 | } |
| 268 | out = append(out, msg) |
| 269 | if stringFromAny(msg["role"]) != "assistant" { |
| 270 | continue |
| 271 | } |
| 272 | toolUseIDs := toolUseIDsInMessage(msg) |
| 273 | if len(toolUseIDs) == 0 { |
| 274 | continue |
| 275 | } |
| 276 | found := map[string]map[string]any{} |
| 277 | needed := map[string]struct{}{} |
| 278 | for _, id := range toolUseIDs { |
| 279 | needed[id] = struct{}{} |
| 280 | } |
| 281 | for j := i + 1; j < len(working) && len(needed) > 0; j++ { |
| 282 | next := working[j] |
| 283 | if next == nil { |
| 284 | continue |
| 285 | } |
| 286 | blocks := contentBlocks(next["content"]) |
| 287 | if len(blocks) == 0 { |
| 288 | continue |
| 289 | } |
| 290 | kept := make([]map[string]any, 0, len(blocks)) |
| 291 | for _, block := range blocks { |
| 292 | if block["type"] == "tool_result" { |
| 293 | id := stringFromAny(block["tool_use_id"]) |
| 294 | if _, ok := needed[id]; ok { |
| 295 | found[id] = block |
| 296 | delete(needed, id) |
| 297 | continue |
| 298 | } |
| 299 | } |
| 300 | kept = append(kept, block) |
| 301 | } |
| 302 | if len(kept) == 0 { |
| 303 | working[j] = nil |
| 304 | } else if len(kept) != len(blocks) { |
| 305 | cp := copyMap(next) |
| 306 | cp["content"] = kept |
| 307 | working[j] = cp |
| 308 | } |
| 309 | } |
| 310 | resultBlocks := make([]map[string]any, 0, len(toolUseIDs)) |
| 311 | for _, id := range toolUseIDs { |
| 312 | if block, ok := found[id]; ok { |
| 313 | resultBlocks = append(resultBlocks, block) |
| 314 | continue |
no test coverage detected