perf(chat): clamp raw tool JSON and hoist tool regexes (#1318) (#1343)

This commit is contained in:
m57
2026-09-28 00:49:25 +03:00
committed by GitHub
parent 18953e368b
commit 673c53503f
3 changed files with 51 additions and 24 deletions
@@ -630,12 +630,23 @@ private fun ToolRawJsonView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
var formatJson by remember { mutableStateOf(true) } var formatJson by remember { mutableStateOf(true) }
val formattedContent = remember(rawContent) { ToolJson.prettyPrintJson(rawContent) } val clampedRaw = remember(rawContent) { ToolJson.clampForDisplay(rawContent) }
val isFormatDifferent = formattedContent != rawContent
val displayText = if (formatJson && isFormatDifferent) formattedContent else rawContent // Full pretty text (for copy) + clamped copy (for display); null when formatting changes nothing.
val formatted by produceState<Pair<String, String>?>(initialValue = null, key1 = rawContent) {
value =
withContext(Dispatchers.Default) {
val full = ToolJson.prettyPrintJson(rawContent)
if (full != rawContent) full to ToolJson.clampForDisplay(full) else null
}
}
val isFormatDifferent = formatted != null
val displayText = formatted?.takeIf { formatJson }?.second ?: clampedRaw
val copyText = formatted?.takeIf { formatJson }?.first ?: rawContent
val highlighted by produceState( val highlighted by produceState(
initialValue = remember(displayText) { AnnotatedString(displayText) }, initialValue = remember(clampedRaw) { AnnotatedString(clampedRaw) },
key1 = displayText, key1 = displayText,
) { ) {
value = value =
@@ -645,7 +656,7 @@ private fun ToolRawJsonView(
} }
CodeTerminalCard( CodeTerminalCard(
textToCopy = displayText, textToCopy = copyText,
modifier = modifier, modifier = modifier,
testTag = "tool_raw_json", testTag = "tool_raw_json",
title = "JSON", title = "JSON",
@@ -84,6 +84,23 @@ internal object ToolCounts {
"sources" to "source", "sources" to "source",
) )
private val S_ENDING_NOUN_REGEX = Regex("(xes|zes|ches|shes|sses)$")
private val CONSONANT_Y_NOUN_REGEX = Regex("[aeiou]y$", RegexOption.IGNORE_CASE)
private val SIBILANT_NOUN_REGEX = Regex("(s|x|z|ch|sh)$", RegexOption.IGNORE_CASE)
private val COUNT_OR_TOTAL_KEY_REGEX = Regex("_count$|_total$")
private val COUNT_OR_TOTAL_STRIP_REGEX = Regex("_(count|total)$")
private val NUM_PREFIX_STRIP_REGEX = Regex("^num_")
private val UNIT_COUNT_REGEX =
Regex(
"""\b(\d+)\s+(results?|items?|files?|matches?|documents?|sources?|searches?|steps?|rows?)\b""",
RegexOption.IGNORE_CASE,
)
private val VERB_COUNT_REGEX =
Regex(
"""\b(?:did|found|returned|listed|searched|matched|updated|created|deleted|processed)\s+(\d+)\b""",
RegexOption.IGNORE_CASE,
)
private fun countFromUnknown(value: JsonElement?): Int? { private fun countFromUnknown(value: JsonElement?): Int? {
if (value is JsonArray) { if (value is JsonArray) {
return if (value.isNotEmpty()) value.size else null return if (value.isNotEmpty()) value.size else null
@@ -109,7 +126,7 @@ internal object ToolCounts {
return "${normalized.dropLast(3)}y" return "${normalized.dropLast(3)}y"
} }
if (Regex("(xes|zes|ches|shes|sses)$").containsMatchIn(normalized) && normalized.length > 3) { if (S_ENDING_NOUN_REGEX.containsMatchIn(normalized) && normalized.length > 3) {
return normalized.dropLast(2) return normalized.dropLast(2)
} }
@@ -134,12 +151,12 @@ internal object ToolCounts {
if (noun.endsWith( if (noun.endsWith(
"y", "y",
) && noun.length > 1 && !Regex("[aeiou]y$", RegexOption.IGNORE_CASE).containsMatchIn(noun) ) && noun.length > 1 && !CONSONANT_Y_NOUN_REGEX.containsMatchIn(noun)
) { ) {
return "${noun.dropLast(1)}ies" return "${noun.dropLast(1)}ies"
} }
if (Regex("(s|x|z|ch|sh)$", RegexOption.IGNORE_CASE).containsMatchIn(noun)) { if (SIBILANT_NOUN_REGEX.containsMatchIn(noun)) {
return "${noun}es" return "${noun}es"
} }
@@ -171,12 +188,12 @@ internal object ToolCounts {
if (key in COUNT_EXCLUDED_KEYS) { if (key in COUNT_EXCLUDED_KEYS) {
continue continue
} }
if (!Regex("_count$|_total$").containsMatchIn(key)) { if (!COUNT_OR_TOTAL_KEY_REGEX.containsMatchIn(key)) {
continue continue
} }
val count = countFromUnknown(value) ?: continue val count = countFromUnknown(value) ?: continue
val stripped = key.lowercase().replace(Regex("_(count|total)$"), "").replace(Regex("^num_"), "") val stripped = key.lowercase().replace(COUNT_OR_TOTAL_STRIP_REGEX, "").replace(NUM_PREFIX_STRIP_REGEX, "")
return countMetric(count, singularizeNoun(stripped).ifEmpty { fallbackNoun }) return countMetric(count, singularizeNoun(stripped).ifEmpty { fallbackNoun })
} }
@@ -194,14 +211,8 @@ internal object ToolCounts {
} }
val unitMatch = val unitMatch =
Regex( UNIT_COUNT_REGEX.find(t)
"""\b(\d+)\s+(results?|items?|files?|matches?|documents?|sources?|searches?|steps?|rows?)\b""", ?: VERB_COUNT_REGEX.find(t)
RegexOption.IGNORE_CASE,
).find(t)
?: Regex(
"""\b(?:did|found|returned|listed|searched|matched|updated|created|deleted|processed)\s+(\d+)\b""",
RegexOption.IGNORE_CASE,
).find(t)
val n = unitMatch?.groupValues?.get(1)?.toIntOrNull() ?: return null val n = unitMatch?.groupValues?.get(1)?.toIntOrNull() ?: return null
val noun = unitMatch.groupValues.getOrNull(2)?.takeIf { it.isNotEmpty() } ?: fallbackNoun val noun = unitMatch.groupValues.getOrNull(2)?.takeIf { it.isNotEmpty() } ?: fallbackNoun
@@ -49,6 +49,14 @@ object ToolResultSummary {
private val ERROR_MSG_KEYS = listOf("message", "reason", "detail") private val ERROR_MSG_KEYS = listOf("message", "reason", "detail")
private val NON_ERROR_TEXT = setOf("", "0", "false", "none", "null", "nil", "ok", "success", "n/a", "na") private val NON_ERROR_TEXT = setOf("", "0", "false", "none", "null", "nil", "ok", "success", "n/a", "na")
private val KEY_SPLIT_REGEX = Regex("[_\\-.]+")
private val WHITESPACE_REGEX = Regex("\\s+")
private val ERROR_SIGNAL_STATUS_REGEX =
Regex(
"\\b(error|failed|failure|fatal|exception)\\b",
RegexOption.IGNORE_CASE,
)
// ── helpers ────────────────────────────────────────────────────────── // ── helpers ──────────────────────────────────────────────────────────
private fun normalize(value: String): String = value.lowercase().trim() private fun normalize(value: String): String = value.lowercase().trim()
@@ -58,7 +66,7 @@ object ToolResultSummary {
private fun titleCase(key: String): String = private fun titleCase(key: String): String =
key key
.split(Regex("[_\\-.]+")) .split(KEY_SPLIT_REGEX)
.filter { it.isNotEmpty() } .filter { it.isNotEmpty() }
.joinToString(" ") { capitalize(it) } .joinToString(" ") { capitalize(it) }
@@ -72,7 +80,7 @@ object ToolResultSummary {
value: String, value: String,
max: Int = 180, max: Int = 180,
): String { ): String {
val c = value.replace(Regex("\\s+"), " ").trim() val c = value.replace(WHITESPACE_REGEX, " ").trim()
return if (c.length > max) "${c.take(max - 1)}…" else c return if (c.length > max) "${c.take(max - 1)}…" else c
} }
@@ -456,10 +464,7 @@ object ToolResultSummary {
return ( return (
(record["success"] as? JsonPrimitive)?.let { !it.isString && it.content == "false" } == true || (record["success"] as? JsonPrimitive)?.let { !it.isString && it.content == "false" } == true ||
(record["ok"] as? JsonPrimitive)?.let { !it.isString && it.content == "false" } == true || (record["ok"] as? JsonPrimitive)?.let { !it.isString && it.content == "false" } == true ||
Regex( ERROR_SIGNAL_STATUS_REGEX.containsMatchIn(status) ||
"\\b(error|failed|failure|fatal|exception)\\b",
RegexOption.IGNORE_CASE,
).containsMatchIn(status) ||
ERROR_KEYS.any { k -> hasMeaningfulErrorValue(record[k]) } ERROR_KEYS.any { k -> hasMeaningfulErrorValue(record[k]) }
) )
} }