ux(chat): tune silent-loop status nudge threshold to 6 rounds and strip leaked tool trace payloads from UI

This commit is contained in:
2026-06-09 15:02:34 -07:00
parent a036f2f28f
commit ef4a06a57c
2 changed files with 15 additions and 6 deletions

View File

@@ -837,16 +837,16 @@ export async function POST(request: Request) {
// guide the model to respond in plain text for conversational inputs. // guide the model to respond in plain text for conversational inputs.
const toolDefs = activeMcpToken ? VIBN_TOOL_DEFINITIONS : []; const toolDefs = activeMcpToken ? VIBN_TOOL_DEFINITIONS : [];
// Every 8 silent rounds or 12 tool calls, gently nudge the model to surface a one-liner // Every 6 silent rounds or 8 tool calls, gently nudge the model to surface a one-liner
// status before continuing. This is the user's only signal of // status before continuing. This is the user's only signal of
// life when a tool chain runs long, but we keep the threshold high so it doesn't distract. // life when a tool chain runs long.
const isSilent = roundsSinceText >= 30 || toolCallsSinceText >= 12; const isSilent = roundsSinceText >= 6 || toolCallsSinceText >= 8;
let extraSystem = isSilent let extraSystem = isSilent
? "\n\n[STATUS NUDGE] You have run " + ? "\n\n[STATUS NUDGE] You have run " +
`${toolCallsSinceText} tool call(s) over ${roundsSinceText} round(s) ` + `${toolCallsSinceText} tool call(s) over ${roundsSinceText} round(s) ` +
"without sending the user any text. Before any more tool calls, " + "without sending the user any text. Before any more tool calls, " +
"send ONE short sentence describing what you are currently working " + "send ONE short sentence describing what you are currently working " +
"on and why. The user is staring at silent tool pills." "on and why. The user is staring at a silent screen."
: ""; : "";
// When withholding tools on round 1 (conversational guard), add a // When withholding tools on round 1 (conversational guard), add a

View File

@@ -479,6 +479,13 @@ function ThinkingBubble({ thoughts }: { thoughts: string }) {
); );
} }
function stripRawToolLogs(text: string): string {
if (!text) return text;
return text
.replace(/(?:\r?\n)*\[tools executed this turn:[\s\S]*?\]/g, "")
.trim();
}
const MessageBubble = React.memo(function MessageBubble({ const MessageBubble = React.memo(function MessageBubble({
msg, msg,
}: { }: {
@@ -573,7 +580,7 @@ const MessageBubble = React.memo(function MessageBubble({
<span <span
style={proseWrap} style={proseWrap}
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: renderMarkdown(msg.content), __html: renderMarkdown(stripRawToolLogs(msg.content)),
}} }}
/> />
)} )}
@@ -666,7 +673,9 @@ function TimelineText({ text }: { text: string }) {
> >
<span <span
style={proseWrap} style={proseWrap}
dangerouslySetInnerHTML={{ __html: renderMarkdown(text) }} dangerouslySetInnerHTML={{
__html: renderMarkdown(stripRawToolLogs(text)),
}}
/> />
</div> </div>
); );