Skip to content

Commit 51797c9

Browse files
committed
fix: improve AI response extraction and fallbacks
1 parent 5169081 commit 51797c9

2 files changed

Lines changed: 29 additions & 12 deletions

File tree

server/api/link/ai.get.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,39 @@ export default eventHandler(async (event) => {
9696
let parsed = destr(content)
9797

9898
// Ensure we always return an object with a slug property
99-
if (typeof parsed === 'string' || parsed === null) {
100-
// Try regex fallback if destr fails
99+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
100+
// Try regex fallback if destr fails to produce an object
101101
const slugMatch = content.match(/"slug"\s*:\s*"([^"]+)"/)
102102
if (slugMatch && slugMatch[1]) {
103103
parsed = { slug: slugMatch[1] }
104104
}
105105
else {
106106
// Last resort fallback: try to find anything that looks like a slug in the string
107-
const fallbackMatch = content.match(/[a-z0-9-]+/i)
108-
if (fallbackMatch && fallbackMatch[0] && content.length < 50) {
109-
parsed = { slug: fallbackMatch[0].toLowerCase() }
107+
// Look for an explicit "slug: <value>" first
108+
const explicitMatch = content.match(/slug[:\s]+([a-z0-9-]+)/i)
109+
if (explicitMatch && explicitMatch[1]) {
110+
parsed = { slug: explicitMatch[1].toLowerCase() }
110111
}
111112
else {
112-
throw createError({
113-
statusCode: 500,
114-
statusMessage: 'Invalid AI response format',
115-
})
113+
// Try to find the most "slug-like" word in the content
114+
// Slugs are usually hyphenated or longer alphanumeric strings
115+
const words = content.match(/[a-z0-9-]+/gi) || []
116+
// Filter out common short words
117+
const candidates = words.filter(w => w.length > 2 && !['the', 'this', 'that', 'your', 'with', 'here', 'your', 'slug'].includes(w.toLowerCase()))
118+
119+
// Prioritize hyphenated words as they are likely intended as slugs
120+
const bestCandidate = candidates.find(w => w.includes('-')) || candidates[0] || words[0]
121+
122+
if (bestCandidate) {
123+
parsed = { slug: bestCandidate.toLowerCase() }
124+
}
125+
else {
126+
console.error('AI response parsing failed. Raw content:', content)
127+
throw createError({
128+
statusCode: 500,
129+
statusMessage: 'Invalid AI response format',
130+
})
131+
}
116132
}
117133
}
118134
}

server/api/link/og-ai.get.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,20 @@ export default eventHandler(async (event) => {
8989
let parsed = destr(content)
9090

9191
// Ensure we always return an object with title and description properties
92-
if (typeof parsed === 'string' || parsed === null) {
92+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
9393
// Attempt to extract title and description as best effort from the raw content
9494
// E.g. "Title: My Title\nDescription: My description"
9595
const titleMatch = content.match(/title:\s*([^\n]+)/i) || content.match(/"title"\s*:\s*"((?:[^"\\]|\\.)+)"/)
9696
const descMatch = content.match(/description:\s*([^\n]+)/i) || content.match(/"description"\s*:\s*"((?:[^"\\]|\\.)+)"/)
9797

9898
if (titleMatch && titleMatch[1] && descMatch && descMatch[1]) {
9999
parsed = {
100-
title: titleMatch[1].trim(),
101-
description: descMatch[1].trim(),
100+
title: titleMatch[1].replace(/^["']|["']$/g, '').trim(),
101+
description: descMatch[1].replace(/^["']|["']$/g, '').trim(),
102102
}
103103
}
104104
else {
105+
console.error('AI OG response parsing failed. Raw content:', content)
105106
throw createError({
106107
statusCode: 500,
107108
statusMessage: 'Invalid AI response format',

0 commit comments

Comments
 (0)