diff --git a/apps/fabro-web/app/routes/run-stages-chat.test.tsx b/apps/fabro-web/app/routes/run-stages-chat.test.tsx index 9ca84db99..be86b89fd 100644 --- a/apps/fabro-web/app/routes/run-stages-chat.test.tsx +++ b/apps/fabro-web/app/routes/run-stages-chat.test.tsx @@ -52,6 +52,58 @@ describe("StageChatView", () => { expect(html).toContain("1m 12s"); }); + test("renders no node for a text-free assistant turn between tool batches", () => { + const html = renderToStaticMarkup( + , + ); + + // The boundary keeps the two batches as separate chips, but contributes + // no element of its own between them. + expect(html.match(/1 tool call/g)).toHaveLength(2); + expect(html).not.toContain('class="prose prose-sm max-w-none"'); + expect(html.match(/class="prose /g)).toHaveLength(1); + expect(html).toContain("Done"); + }); + test("connects a long prompt's expand button to its controlled content", () => { const html = renderToStaticMarkup( ); case "assistant": { + const hasText = turn.content.trim().length > 0; const metric = turnMetric(turn); const isFinal = turnIndex === lastAssistantTurnIndex && !stageActive; + const showFooter = isFinal && Boolean(metric || duration); + // A text-free assistant turn is the boundary between two batches + // of tool calls, kept in the turn stream so those batches stay + // separate chips. It has nothing to show, and an empty node would + // still take a slot in this gap-4 column, doubling the space + // between the chips on either side of it. + if (!hasText && !showFooter) return null; return (
- - {isFinal && (metric || duration) && ( + {hasText && } + {showFooter && (
{metric && {metric}} {duration && {duration}}