From d37e1d3dc3ceef72c0bd74dbd55c86f0fb9eefcc Mon Sep 17 00:00:00 2001 From: Dotta Date: Thu, 5 Mar 2026 09:25:03 -0600 Subject: [PATCH] preserve thinking delta whitespace in runlog streaming --- packages/adapters/cursor-local/src/ui/parse-stdout.ts | 8 +++++--- server/src/__tests__/cursor-local-adapter.test.ts | 11 +++++++++++ ui/src/components/ActiveAgentsPanel.tsx | 4 ++-- ui/src/components/LiveRunWidget.tsx | 4 ++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/adapters/cursor-local/src/ui/parse-stdout.ts b/packages/adapters/cursor-local/src/ui/parse-stdout.ts index 9690b507..047a9041 100644 --- a/packages/adapters/cursor-local/src/ui/parse-stdout.ts +++ b/packages/adapters/cursor-local/src/ui/parse-stdout.ts @@ -218,11 +218,13 @@ export function parseCursorStdoutLine(line: string, ts: string): TranscriptEntry } if (type === "thinking") { - const text = asString(parsed.text).trim() || asString(asRecord(parsed.delta)?.text).trim(); + const textFromTopLevel = asString(parsed.text); + const textFromDelta = asString(asRecord(parsed.delta)?.text); + const text = textFromTopLevel.length > 0 ? textFromTopLevel : textFromDelta; const subtype = asString(parsed.subtype).trim().toLowerCase(); const isDelta = subtype === "delta" || asRecord(parsed.delta) !== null; - if (!text) return []; - return [{ kind: "thinking", ts, text, ...(isDelta ? { delta: true } : {}) }]; + if (!text.trim()) return []; + return [{ kind: "thinking", ts, text: isDelta ? text : text.trim(), ...(isDelta ? { delta: true } : {}) }]; } if (type === "tool_call") { diff --git a/server/src/__tests__/cursor-local-adapter.test.ts b/server/src/__tests__/cursor-local-adapter.test.ts index aad83bc7..22bb4ba6 100644 --- a/server/src/__tests__/cursor-local-adapter.test.ts +++ b/server/src/__tests__/cursor-local-adapter.test.ts @@ -164,6 +164,17 @@ describe("cursor ui stdout parser", () => { ), ).toEqual([{ kind: "thinking", ts, text: "planning next command", delta: true }]); + expect( + parseCursorStdoutLine( + JSON.stringify({ + type: "thinking", + subtype: "delta", + text: " with preserved leading space", + }), + ts, + ), + ).toEqual([{ kind: "thinking", ts, text: " with preserved leading space", delta: true }]); + expect( parseCursorStdoutLine( JSON.stringify({ diff --git a/ui/src/components/ActiveAgentsPanel.tsx b/ui/src/components/ActiveAgentsPanel.tsx index 53a1af9f..d9db179d 100644 --- a/ui/src/components/ActiveAgentsPanel.tsx +++ b/ui/src/components/ActiveAgentsPanel.tsx @@ -100,8 +100,8 @@ function parseStdoutChunk( const summarized: Array<{ text: string; tone: FeedTone; thinkingDelta?: boolean }> = []; const appendSummary = (entry: TranscriptEntry) => { if (entry.kind === "thinking" && entry.delta) { - const text = entry.text.trim(); - if (!text) return; + const text = entry.text; + if (!text.trim()) return; const last = summarized[summarized.length - 1]; if (last && last.thinkingDelta) { last.text += text; diff --git a/ui/src/components/LiveRunWidget.tsx b/ui/src/components/LiveRunWidget.tsx index 0febefd4..253152d0 100644 --- a/ui/src/components/LiveRunWidget.tsx +++ b/ui/src/components/LiveRunWidget.tsx @@ -111,8 +111,8 @@ function parseStdoutChunk( const summarized: Array<{ text: string; tone: FeedTone; thinkingDelta?: boolean }> = []; const appendSummary = (entry: TranscriptEntry) => { if (entry.kind === "thinking" && entry.delta) { - const text = entry.text.trim(); - if (!text) return; + const text = entry.text; + if (!text.trim()) return; const last = summarized[summarized.length - 1]; if (last && last.thinkingDelta) { last.text += text;