( messages: Message[], teamInfo?: TeamInfo, startingParentUuidHint?: UUID, allMessages?: readonly Message[], )
| 1443 | // messagesToKeep → not a prefix → not tracked → CB gets parentUuid=null |
| 1444 | // (correct: truncates --continue chain at compact boundary). |
| 1445 | export async function recordTranscript( |
| 1446 | messages: Message[], |
| 1447 | teamInfo?: TeamInfo, |
| 1448 | startingParentUuidHint?: UUID, |
| 1449 | allMessages?: readonly Message[], |
| 1450 | ): Promise<UUID | null> { |
| 1451 | const cleanedMessages = cleanMessagesForLogging(messages, allMessages) |
| 1452 | const sessionId = getSessionId() as UUID |
| 1453 | const messageSet = await getSessionMessages(sessionId) |
| 1454 | const newMessages: typeof cleanedMessages = [] |
| 1455 | let startingParentUuid: UUID | undefined = startingParentUuidHint |
| 1456 | let seenNewMessage = false |
| 1457 | for (const m of cleanedMessages) { |
| 1458 | if (messageSet.has(m.uuid as UUID)) { |
| 1459 | // Only track skipped messages that form a prefix. After compaction, |
| 1460 | // messagesToKeep appear AFTER new CB/summary, so this skips them. |
| 1461 | if (!seenNewMessage && isChainParticipant(m)) { |
| 1462 | startingParentUuid = m.uuid as UUID |
| 1463 | } |
| 1464 | } else { |
| 1465 | newMessages.push(m) |
| 1466 | seenNewMessage = true |
| 1467 | } |
| 1468 | } |
| 1469 | if (newMessages.length > 0) { |
| 1470 | await getProject().insertMessageChain( |
| 1471 | newMessages, |
| 1472 | false, |
| 1473 | undefined, |
| 1474 | startingParentUuid, |
| 1475 | teamInfo, |
| 1476 | ) |
| 1477 | } |
| 1478 | // Return the last ACTUALLY recorded chain-participant's UUID, OR the |
| 1479 | // prefix-tracked UUID if no new chain participants were recorded. This lets |
| 1480 | // callers (useLogMessages) maintain the correct parent chain even when the |
| 1481 | // slice is all-recorded (rewind, /resume scenarios where every message is |
| 1482 | // already in messageSet). Progress is skipped — it's written to the JSONL |
| 1483 | // but nothing chains TO it (see isChainParticipant). |
| 1484 | const lastRecorded = newMessages.findLast(isChainParticipant) |
| 1485 | return (lastRecorded?.uuid as UUID | undefined) ?? startingParentUuid ?? null |
| 1486 | } |
| 1487 | |
| 1488 | export async function recordSidechainTranscript( |
| 1489 | messages: Message[], |
no test coverage detected