Skip to content

Commit c3d3ed4

Browse files
commit
1 parent f5b0ebc commit c3d3ed4

1 file changed

Lines changed: 49 additions & 12 deletions

File tree

src/App/src/components/content/streaming/StreamingBufferMessage.tsx

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,68 @@ const jsonToMarkdown = (value: any, depth = 0): string => {
6565
/**
6666
* Detect raw JSON blocks in the streaming buffer and replace them with a
6767
* readable Markdown rendering so the Details section doesn't expose raw JSON.
68-
* Lines that already sit inside an existing fenced code block are left alone.
68+
* Handles both bare JSON blocks and fenced code blocks containing JSON
69+
* (e.g. ```json ... ``` or ``` { ... } ```).
6970
*/
7071
const formatBufferContent = (content: string): string => {
7172
if (!content) return content;
7273

7374
const lines = content.split('\n');
7475
const out: string[] = [];
75-
let insideExistingFence = false;
7676
let i = 0;
7777

78+
const tryRenderJsonBlock = (block: string): string | null => {
79+
const trimmed = block.trim();
80+
if (!trimmed) return null;
81+
if (!(trimmed.startsWith('{') || trimmed.startsWith('['))) return null;
82+
try {
83+
const parsed = JSON.parse(trimmed);
84+
if (parsed === null || typeof parsed !== 'object') return null;
85+
return jsonToMarkdown(parsed);
86+
} catch {
87+
return null;
88+
}
89+
};
90+
7891
while (i < lines.length) {
7992
const line = lines[i];
8093
const trimmed = line.trim();
8194

95+
// Fenced code block — try to render as readable JSON if applicable
8296
if (trimmed.startsWith('```')) {
83-
insideExistingFence = !insideExistingFence;
84-
out.push(line);
85-
i++;
97+
const fenceLang = trimmed.replace(/^```/, '').trim().toLowerCase();
98+
// Find closing fence
99+
let endIdx = -1;
100+
for (let j = i + 1; j < lines.length; j++) {
101+
if (lines[j].trim().startsWith('```')) {
102+
endIdx = j;
103+
break;
104+
}
105+
}
106+
if (endIdx === -1) {
107+
// Unterminated fence — pass remaining lines through unchanged
108+
out.push(line);
109+
i++;
110+
continue;
111+
}
112+
113+
const inner = lines.slice(i + 1, endIdx).join('\n');
114+
const isJsonLang = fenceLang === 'json' || fenceLang === '';
115+
const rendered = isJsonLang ? tryRenderJsonBlock(inner) : null;
116+
if (rendered !== null) {
117+
out.push(rendered);
118+
out.push('');
119+
} else {
120+
// Keep original fenced block as-is
121+
out.push(line);
122+
for (let j = i + 1; j <= endIdx; j++) out.push(lines[j]);
123+
}
124+
i = endIdx + 1;
86125
continue;
87126
}
88127

89-
if (!insideExistingFence && (trimmed.startsWith('{') || trimmed.startsWith('['))) {
90-
// Try to capture a balanced JSON block starting at this line
128+
// Bare JSON block (not inside a fence)
129+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
91130
let depth = 0;
92131
let endIdx = -1;
93132
for (let j = i; j < lines.length; j++) {
@@ -103,14 +142,12 @@ const formatBufferContent = (content: string): string => {
103142
}
104143
if (endIdx !== -1) {
105144
const block = lines.slice(i, endIdx + 1).join('\n');
106-
try {
107-
const parsed = JSON.parse(block);
108-
out.push(jsonToMarkdown(parsed));
145+
const rendered = tryRenderJsonBlock(block);
146+
if (rendered !== null) {
147+
out.push(rendered);
109148
out.push('');
110149
i = endIdx + 1;
111150
continue;
112-
} catch {
113-
// Not valid JSON — fall through and keep the original line
114151
}
115152
}
116153
}

0 commit comments

Comments
 (0)