diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt index 7308266..309d934 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt @@ -215,9 +215,20 @@ sealed class TranscriptItem { * Only ever consulted when the call is first folded in. That is what makes the name stable -- a run * keeps whatever it was called when it started, however many calls arrive at either end of it * afterwards. + * + * A question to the reader is in a run of its own, which is what puts it on the transcript as a row + * rather than inside a collapsed "Called 6 tools" card. Two things follow from being alone: it is + * always visible, since a run of one is drawn as itself rather than as a group; and the calls + * around it fall into a group before it and a group after it, so where the reader was asked + * something is legible in the shape of the transcript without opening anything. It ends the run + * before it as well as starting a fresh one after -- the moment somebody was asked is a boundary in + * the work, not a gap in the middle of one run. */ -private fun runIdFor(items: List, id: String): String = - (items.lastOrNull() as? TranscriptItem.ToolRun)?.runId ?: id +private fun runIdFor(items: List, id: String, tool: String): String { + val previous = items.lastOrNull() as? TranscriptItem.ToolRun ?: return id + if (tool == ASK_USER_QUESTION || previous.tool == ASK_USER_QUESTION) return id + return previous.runId +} /** * Puts a page of older items in front of the ones already loaded, healing whatever the page @@ -310,8 +321,15 @@ private fun adoptRun( earlier: List, later: List, ): List { - val joining = (later.firstOrNull() as? TranscriptItem.ToolRun)?.runId ?: return earlier - val tail = earlier.takeLastWhile { it is TranscriptItem.ToolRun } + val first = later.firstOrNull() as? TranscriptItem.ToolRun ?: return earlier + // A question is in a run of its own on both sides of the join, the same as it would be had + // the two pages been folded as one -- see `runIdFor`. Without this the heal would merge a + // group straight through the row the reader was asked something on. + if (first.tool == ASK_USER_QUESTION) return earlier + val joining = first.runId + val tail = earlier.takeLastWhile { + it is TranscriptItem.ToolRun && it.tool != ASK_USER_QUESTION + } if (tail.isEmpty()) return earlier return earlier.dropLast(tail.size) + tail.map { (it as TranscriptItem.ToolRun).copy(runId = joining) } @@ -337,7 +355,7 @@ fun foldEvent(items: List, entry: SeqEvent): List, entry: SeqEvent): List