fix(app): wrap unprotected JSON.parse calls in try/catch

SSE stream callbacks and AI response parsing now handle malformed data
gracefully instead of throwing unhandled exceptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-04 22:11:18 +00:00
co-authored by Claude Opus 4.6
parent 9ba4854024
commit 82f1e99324
4 changed files with 30 additions and 19 deletions
+8 -6
View File
@@ -51,12 +51,14 @@ export const claudeAdapter: AIAdapter = {
}
await readSSE(res, (data) => {
const parsed = JSON.parse(data)
if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
onToken(parsed.delta.text)
} else if (parsed.type === 'error') {
onError(parsed.error?.message ?? 'Claude stream error')
}
try {
const parsed = JSON.parse(data)
if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
onToken(parsed.delta.text)
} else if (parsed.type === 'error') {
onError(parsed.error?.message ?? 'Claude stream error')
}
} catch { /* malformed SSE chunk */ }
}, onError, options.signal)
},
}
@@ -60,9 +60,11 @@ export const openrouterAdapter: AIAdapter = {
await readSSE(res, (data) => {
if (data === '[DONE]') return
const parsed = JSON.parse(data)
const delta = parsed.choices?.[0]?.delta?.content
if (delta) onToken(delta)
try {
const parsed = JSON.parse(data)
const delta = parsed.choices?.[0]?.delta?.content
if (delta) onToken(delta)
} catch { /* malformed SSE chunk */ }
}, onError, options.signal)
},
}
+13 -9
View File
@@ -209,12 +209,14 @@ async function streamClaude(
}
await readSSE(res, (data) => {
const parsed = JSON.parse(data)
if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
onToken(parsed.delta.text)
} else if (parsed.type === 'error') {
onError(parsed.error?.message ?? 'Claude stream error')
}
try {
const parsed = JSON.parse(data)
if (parsed.type === 'content_block_delta' && parsed.delta?.text) {
onToken(parsed.delta.text)
} else if (parsed.type === 'error') {
onError(parsed.error?.message ?? 'Claude stream error')
}
} catch { /* malformed SSE chunk */ }
}, onError, signal)
}
@@ -261,9 +263,11 @@ async function streamOpenRouter(
await readSSE(res, (data) => {
if (data === '[DONE]') return
const parsed = JSON.parse(data)
const delta = parsed.choices?.[0]?.delta?.content
if (delta) onToken(delta)
try {
const parsed = JSON.parse(data)
const delta = parsed.choices?.[0]?.delta?.content
if (delta) onToken(delta)
} catch { /* malformed SSE chunk */ }
}, onError, signal)
}
@@ -78,7 +78,10 @@ export function useSimilarContent() {
// Extract JSON array from response
const match = text.match(/\[[\s\S]*\]/)
if (match) {
const parsed = JSON.parse(match[0]) as { title: string; reason: string }[]
let parsed: { title: string; reason: string }[]
try {
parsed = JSON.parse(match[0]) as { title: string; reason: string }[]
} catch { return }
const items: SimilarItem[] = parsed.slice(0, 3).map(p => ({
title: p.title,
type,