diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/Events.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/Events.kt index 9a4c337..29a6d91 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/Events.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/Events.kt @@ -29,8 +29,7 @@ sealed class SessionEvent { val options: List, /** The tool call this is permission for, or null when it is not about one. */ val about: String?, - ) : - SessionEvent() + ) : SessionEvent() data class Answered(val id: String, val answer: String) : SessionEvent() diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/MemoryNote.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/MemoryNote.kt index cdfcb4f..e298c6e 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/MemoryNote.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/MemoryNote.kt @@ -15,12 +15,12 @@ import androidx.compose.ui.unit.dp /** * An assistant's reply, with anything it says it remembered drawn as a note rather than as markup. * - * Claude Code marks a sentence that came from its stored memory by wrapping it in - * ``. Markdown has nothing to say about that, so it arrived on screen as - * literal angle brackets in the middle of a sentence -- which reads as the model having emitted - * broken HTML. It is really the opposite: a claim about where something came from, which is worth - * showing, because "I was told this before" and "I worked this out just now" are different things - * and the reader cannot otherwise tell them apart. + * Claude Code marks a sentence that came from its stored memory by wrapping it in ``. Markdown has nothing to say about that, so it arrived on screen as literal + * angle brackets in the middle of a sentence -- which reads as the model having emitted broken + * HTML. It is really the opposite: a claim about where something came from, which is worth showing, + * because "I was told this before" and "I worked this out just now" are different things and the + * reader cannot otherwise tell them apart. * * A tag that has not finished arriving is left alone. Streaming means the closing tag may be * seconds away, and a half-written marker is not a marker yet. @@ -81,8 +81,7 @@ fun splitMemoryNotes(text: String): List { for (match in MEMORY_NOTE.findAll(text)) { val before = text.substring(at, match.range.first) if (before.isNotBlank()) parts += MessagePart.Prose(before.trim()) - val files = - match.groupValues[1].split(",").map { it.trim() }.filter { it.isNotEmpty() } + val files = match.groupValues[1].split(",").map { it.trim() }.filter { it.isNotEmpty() } parts += MessagePart.Remembered(match.groupValues[2].trim(), files) at = match.range.last + 1 } 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 d73c979..d50ddc4 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt @@ -84,8 +84,8 @@ sealed class TranscriptItem { * * On the call's own row rather than beside it: the ask used to arrive as a second card * repeating the input verbatim, so the reader saw the same command twice and had to work - * out that it was one event. The backend says which call a permission is about, so this - * is a fact rather than a match on the input. + * out that it was one event. The backend says which call a permission is about, so this is + * a fact rather than a match on the input. */ val ask: QuestionCard? = null, ) : TranscriptItem() @@ -138,7 +138,10 @@ fun foldEvent(items: List, event: SessionEvent): List v.isNotBlank() } } + val description = DESCRIPTIONS.firstNotNullOfOrNull { + json.optString(it).takeIf { v -> v.isNotBlank() } + } val rest = - json.keys() + json + .keys() .asSequence() .filter { it != subjectKey || subject == null } .filter { it !in DESCRIPTIONS || description == null } @@ -107,7 +115,9 @@ fun ToolInputView(tool: String, input: String, modifier: Modifier = Modifier) { fontFamily = FontFamily.Monospace, softWrap = false, modifier = - Modifier.padding(top = 4.dp).fillMaxWidth().horizontalScroll(rememberScrollState()), + Modifier.padding(top = 4.dp) + .fillMaxWidth() + .horizontalScroll(rememberScrollState()), ) } parsed.rest.forEach { @@ -136,14 +146,21 @@ private fun highlighted(code: String, language: SyntaxLanguage?): AnnotatedStrin return remember(code, language, theme, plain) { if (language == null) return@remember AnnotatedString(code) val marks = - Highlights.Builder(code = code, language = language, theme = theme).build().getHighlights() + Highlights.Builder(code = code, language = language, theme = theme) + .build() + .getHighlights() buildAnnotatedString { append(code) marks.forEach { mark -> when (mark) { is ColorHighlight -> addStyle( - SpanStyle(color = androidx.compose.ui.graphics.Color(mark.rgb or 0xFF000000.toInt())), + SpanStyle( + color = + androidx.compose.ui.graphics.Color( + mark.rgb or 0xFF000000.toInt() + ) + ), mark.location.start, mark.location.end, )