( messages: Message[], teamInfo?: TeamInfo, startingParentUuidHint?: UUID, allMessages?: readonly Message[], )
| 1406 | // messagesToKeep → not a prefix → not tracked → CB gets parentUuid=null |
| 1407 | // (correct: truncates --continue chain at compact boundary). |
| 1408 | export async function recordTranscript( |
| 1409 | messages: Message[], |
| 1410 | teamInfo?: TeamInfo, |
| 1411 | startingParentUuidHint?: UUID, |
| 1412 | allMessages?: readonly Message[], |
| 1413 | ): Promise<UUID | null> { |
| 1414 | const cleanedMessages = cleanMessagesForLogging(messages, allMessages) |
| 1415 | const sessionId = getSessionId() as UUID |
| 1416 | const messageSet = await getSessionMessages(sessionId) |
| 1417 | const newMessages: typeof cleanedMessages = [] |
| 1418 | let startingParentUuid: UUID | undefined = startingParentUuidHint |
| 1419 | let seenNewMessage = false |
| 1420 | for (const m of cleanedMessages) { |
| 1421 | if (messageSet.has(m.uuid as UUID)) { |
| 1422 | // Only track skipped messages that form a prefix. After compaction, |
| 1423 | // messagesToKeep appear AFTER new CB/summary, so this skips them. |
| 1424 | if (!seenNewMessage && isChainParticipant(m)) { |
| 1425 | startingParentUuid = m.uuid as UUID |
| 1426 | } |
| 1427 | } else { |
| 1428 | newMessages.push(m) |
| 1429 | seenNewMessage = true |
| 1430 | } |
| 1431 | } |
| 1432 | if (newMessages.length > 0) { |
| 1433 | await getProject().insertMessageChain( |
| 1434 | newMessages, |
| 1435 | false, |
| 1436 | undefined, |
| 1437 | startingParentUuid, |
| 1438 | teamInfo, |
| 1439 | ) |
| 1440 | } |
| 1441 | // Return the last ACTUALLY recorded chain-participant's UUID, OR the |
| 1442 | // prefix-tracked UUID if no new chain participants were recorded. This lets |
| 1443 | // callers (useLogMessages) maintain the correct parent chain even when the |
| 1444 | // slice is all-recorded (rewind, /resume scenarios where every message is |
| 1445 | // already in messageSet). Progress is skipped — it's written to the JSONL |
| 1446 | // but nothing chains TO it (see isChainParticipant). |
| 1447 | const lastRecorded = newMessages.findLast(isChainParticipant) |
| 1448 | return (lastRecorded?.uuid as UUID | undefined) ?? startingParentUuid ?? null |
| 1449 | } |
| 1450 | |
| 1451 | export async function recordSidechainTranscript( |
| 1452 | messages: Message[], |
no test coverage detected