package com.example.aiapp import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier /** * The mark a compaction leaves in the transcript. * * A divider rather than something anybody said: everything above it is out of the session's context * now, and that is a fact about the conversation, not a turn in it. It has no collapsed form -- it * is already one line, and there is nothing behind it to open. Drawn by [TranscriptDivider], which * a clear also uses, so the two marks cannot drift apart. * * Blue is [commandColor]: the session acting on itself rather than working on what was asked of it, * which is the same thing the status line says while the compaction runs. */ @Composable fun CompactedRow(item: TranscriptItem.CompactedNote, modifier: Modifier = Modifier) { TranscriptDivider(compactionSummary(item), commandColor, modifier) } /** * What to say about a compaction: the two sizes, and nothing else. * * The counts are the whole point -- "a million tokens became ten thousand" is the reader's answer * to why the wait was worth it -- and they are all this says, because a divider is read in passing. * When they were not reported this says only that a compaction happened, rather than filling in a * plausible number or explaining at length what was missing. */ fun compactionSummary(item: TranscriptItem.CompactedNote): String { val pre = item.preTokens val post = item.postTokens return if (pre != null && post != null) { "Compacted • ${tokens(pre)} → ${tokens(post)} tok" } else { "Compacted" } } /** * A token count as a reader reads one. * * Shared with the status row rather than formatted at each: the divider and the row report the same * quantity about the same moment, and one of them grouping its thousands while the other did not * read as two different measurements. */ fun tokens(count: Long): String = "%,d".format(count) /** * What the working indicator says while a compaction is running. * * Elapsed time and nothing else, because elapsed time is all there is: the CLI announces that a * compaction has begun and then says nothing until it has finished, so any bar, percentage or * estimate here would be this screen's guess wearing a measurement's clothes. Knowing it has been * going forty seconds is what a reader actually wants -- it is the difference between waiting and * going to look at why. * * [seconds] is null when this device did not see the compaction start, which is what opening a * session that is already compacting looks like. That case says only "compacting": no number is the * honest answer, and a number counted from the moment the screen opened would be wrong in the * direction that matters, since a compaction somebody is asking about is a long one. */ fun compactingLabel(seconds: Long?): String = when { seconds == null -> "compacting" seconds < 60 -> "compacting ${seconds}s" else -> "compacting ${seconds / 60}m ${seconds % 60}s" }