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:
co-authored by
Claude Opus 4.6
parent
9ba4854024
commit
82f1e99324
@@ -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)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user