Files
openchamber/packages/ui/src/components/chat/message/parts/generatedJsonResult.ts
T
Bohdan Triapitsyn 9c1eb755f9 fix: prevent embedded JSON examples from rendering as result cards
Only parse full-message generated JSON results
Keep markdown prose with JSON examples rendered normally
Add regression coverage for embedded JSON examples
2026-06-29 12:19:28 +03:00

62 lines
1.8 KiB
TypeScript

type GeneratedCommitResult = {
kind: 'commit';
subject: string;
highlights: string[];
raw: string;
};
type GeneratedPrResult = {
kind: 'pr';
title: string;
body: string;
raw: string;
};
export type GeneratedResult = GeneratedCommitResult | GeneratedPrResult;
const parseJsonObjects = (value: string): Record<string, unknown>[] => {
const text = value.trim();
const candidates: string[] = [];
const fencedMatch = text.match(/^```(?:json)?\s*([\s\S]*?)```$/i);
if (fencedMatch?.[1]) {
candidates.push(fencedMatch[1].trim());
}
if (text.startsWith('{') && text.endsWith('}')) {
candidates.push(text);
}
const parsed: Record<string, unknown>[] = [];
for (const candidate of candidates) {
try {
const item = JSON.parse(candidate) as unknown;
if (item && typeof item === 'object' && !Array.isArray(item)) {
parsed.push(item as Record<string, unknown>);
}
} catch {
// Ignore non-JSON prose; the model may include markdown before the object.
}
}
return parsed;
};
export const parseGeneratedJsonResult = (value: string): GeneratedResult | null => {
for (const item of parseJsonObjects(value)) {
const subject = typeof item.subject === 'string' ? item.subject.trim() : '';
const highlights = Array.isArray(item.highlights)
? item.highlights.filter((entry) => typeof entry === 'string').map((entry) => entry.trim()).filter(Boolean).slice(0, 3)
: [];
if (subject) {
return { kind: 'commit', subject, highlights, raw: JSON.stringify({ subject, highlights }, null, 2) };
}
const title = typeof item.title === 'string' ? item.title.trim() : '';
const body = typeof item.body === 'string' ? item.body.trim() : '';
if (title || body) {
return { kind: 'pr', title, body, raw: JSON.stringify({ title, body }, null, 2) };
}
}
return null;
};