(messages: Message[])
| 1479 | * - Any assistant message |
| 1480 | */ |
| 1481 | export function reorderAttachmentsForAPI(messages: Message[]): Message[] { |
| 1482 | // We build `result` backwards (push) and reverse once at the end — O(N). |
| 1483 | // Using unshift inside the loop would be O(N²). |
| 1484 | const result: Message[] = [] |
| 1485 | // Attachments are pushed as we encounter them scanning bottom-up, so |
| 1486 | // this buffer holds them in reverse order (relative to the input array). |
| 1487 | const pendingAttachments: AttachmentMessage[] = [] |
| 1488 | |
| 1489 | // Scan from the bottom up |
| 1490 | for (let i = messages.length - 1; i >= 0; i--) { |
| 1491 | const message = messages[i]! |
| 1492 | |
| 1493 | if (message.type === 'attachment') { |
| 1494 | // Collect attachment to bubble up |
| 1495 | pendingAttachments.push(message) |
| 1496 | } else { |
| 1497 | // Check if this is a stopping point |
| 1498 | const isStoppingPoint = |
| 1499 | message.type === 'assistant' || |
| 1500 | (message.type === 'user' && |
| 1501 | Array.isArray(message.message.content) && |
| 1502 | message.message.content[0]?.type === 'tool_result') |
| 1503 | |
| 1504 | if (isStoppingPoint && pendingAttachments.length > 0) { |
| 1505 | // Hit a stopping point — attachments stop here (go after the stopping point). |
| 1506 | // pendingAttachments is already reversed; after the final result.reverse() |
| 1507 | // they will appear in original order right after `message`. |
| 1508 | for (let j = 0; j < pendingAttachments.length; j++) { |
| 1509 | result.push(pendingAttachments[j]!) |
| 1510 | } |
| 1511 | result.push(message) |
| 1512 | pendingAttachments.length = 0 |
| 1513 | } else { |
| 1514 | // Regular message |
| 1515 | result.push(message) |
| 1516 | } |
| 1517 | } |
| 1518 | } |
| 1519 | |
| 1520 | // Any remaining attachments bubble all the way to the top. |
| 1521 | for (let j = 0; j < pendingAttachments.length; j++) { |
| 1522 | result.push(pendingAttachments[j]!) |
| 1523 | } |
| 1524 | |
| 1525 | result.reverse() |
| 1526 | return result |
| 1527 | } |
| 1528 | |
| 1529 | export function isSystemLocalCommandMessage( |
| 1530 | message: Message, |
no test coverage detected