Skip to content

Commit db40a13

Browse files
feat(WebView): truncate older Screen elements bubbles in chat UI to "no longer relevant", keep newest 3
1 parent 8e16350 commit db40a13

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

index.html

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5259,6 +5259,71 @@
52595259
/* ════════════════════════════════════════════════════════
52605260
CHAT
52615261
════════════════════════════════════════════════════════ */
5262+
/**
5263+
* Collapses older "Screen elements:" user bubbles in the visible chat to
5264+
* "no longer relevant", keeping only the N most recent intact
5265+
* (N = _executionPolicy.maxRelevantScreenElementMessages, default 3).
5266+
* Only user bubbles are affected. Termux output bubbles are not touched.
5267+
* Called after every addUserBubble() and after _renderRestoredChatBubbles().
5268+
*/
5269+
function _truncateScreenElementBubblesInDom() {
5270+
const marker = (_operationalTuning && _operationalTuning.screenElementsMarker)
5271+
? _operationalTuning.screenElementsMarker
5272+
: 'Screen elements:';
5273+
const termuxMarker = 'Termux output:';
5274+
const noLongerRelevant = 'no longer relevant';
5275+
const maxKeep = (_executionPolicy && typeof _executionPolicy.maxRelevantScreenElementMessages === 'number')
5276+
? _executionPolicy.maxRelevantScreenElementMessages
5277+
: 3;
5278+
5279+
// Collect all user bubbles that contain screen elements (but not termux-only bubbles)
5280+
const allUserBubbles = [...document.querySelectorAll('#chat-messages .bubble-wrap.user-wrap .bubble.user')];
5281+
const screenElementBubbles = allUserBubbles.filter(el => {
5282+
const text = el.textContent || '';
5283+
const hasScreen = text.toLowerCase().includes(marker.toLowerCase());
5284+
if (!hasScreen) return false;
5285+
// Exclude bubbles where the only output is Termux (no Screen elements section)
5286+
return true;
5287+
});
5288+
5289+
if (screenElementBubbles.length <= maxKeep) return;
5290+
5291+
// The oldest ones (all but the last maxKeep) get truncated
5292+
const toTruncate = screenElementBubbles.slice(0, screenElementBubbles.length - maxKeep);
5293+
for (const bubble of toTruncate) {
5294+
const text = bubble.textContent || '';
5295+
const markerIdx = text.toLowerCase().indexOf(marker.toLowerCase());
5296+
if (markerIdx < 0) continue;
5297+
// Check if already replaced
5298+
const afterMarker = text.substring(markerIdx + marker.length).trim();
5299+
if (afterMarker.toLowerCase() === noLongerRelevant) continue;
5300+
// Replace the text content: keep everything before the marker, add marker + no longer relevant
5301+
const prefix = text.substring(0, markerIdx);
5302+
// We need to update only the text node (the bubble may contain an img child for screenshots)
5303+
// Strategy: walk child nodes, replace text nodes to rewrite content
5304+
_replaceBubbleTextUpToMarker(bubble, prefix, marker, noLongerRelevant);
5305+
}
5306+
}
5307+
5308+
/**
5309+
* Rewrites the text content of a user bubble element so that everything from
5310+
* the screen-elements marker onwards is replaced with "no longer relevant",
5311+
* while preserving any non-text child elements (e.g. screenshot thumbnails).
5312+
*/
5313+
function _replaceBubbleTextUpToMarker(bubble, prefix, marker, replacement) {
5314+
// Build the new plain-text portion
5315+
const newPlainText = prefix + marker + ' ' + replacement;
5316+
// Remove all text nodes (keep element children like img)
5317+
const childNodes = [...bubble.childNodes];
5318+
for (const node of childNodes) {
5319+
if (node.nodeType === Node.TEXT_NODE) {
5320+
node.remove();
5321+
}
5322+
}
5323+
// Prepend the new text as a text node at the start
5324+
bubble.insertBefore(document.createTextNode(newPlainText), bubble.firstChild);
5325+
}
5326+
52625327
function addUserBubble(text, imageDataUri) {
52635328
const wrap = document.createElement('div');
52645329
wrap.className = 'bubble-wrap user-wrap';
@@ -5271,6 +5336,7 @@
52715336
: '';
52725337
wrap.innerHTML = `<div class="bubble user">${escHtml(text)}${thumbHtml}</div>${undoBtnHtml}`;
52735338
document.getElementById('chat-messages').appendChild(wrap);
5339+
_truncateScreenElementBubblesInDom();
52745340
scrollToBottom();
52755341
}
52765342
/** Shows a placeholder user-side bubble with a spinner while waiting for Termux output. */
@@ -5954,6 +6020,8 @@
59546020
if (m.role === 'user') addUserBubble(m.text || '', m.imageDataUri);
59556021
else addModelBubble(m.text, false);
59566022
}
6023+
// After restoring all bubbles, apply screen-element truncation once
6024+
_truncateScreenElementBubblesInDom();
59576025
}
59586026

59596027
/**

0 commit comments

Comments
 (0)