Ajoute le pipeline PageSpec (validation, rendu, publication /p/{slug}),
les démos TipTap /demo, et le simulateur Carnot (modes frigo/PAC/moteur,
énergie kJ vs puissance W, unités K/°C/°F) avec correctifs d’équations KaTeX.
Co-authored-by: Cursor <cursoragent@cursor.com>
75 lines
1.8 KiB
TypeScript
75 lines
1.8 KiB
TypeScript
import type { InteractiveDemoV1, ValidationIssue } from '@/lib/interactive-demo'
|
|
|
|
export type GenerateInteractiveDemoResponse =
|
|
| { ok: true; demo: InteractiveDemoV1; attempts: number }
|
|
| {
|
|
ok: false
|
|
error: string
|
|
issues?: ValidationIssue[]
|
|
quotaExceeded?: boolean
|
|
status?: number
|
|
}
|
|
|
|
export async function generateInteractiveDemo(params: {
|
|
content: string
|
|
selection?: string | null
|
|
lang?: string
|
|
noteId?: string
|
|
}): Promise<GenerateInteractiveDemoResponse> {
|
|
const controller = new AbortController()
|
|
const timeout = setTimeout(() => controller.abort(), 170_000)
|
|
let res: Response
|
|
try {
|
|
res = await fetch('/api/ai/interactive-demo', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
content: params.content,
|
|
selection: params.selection,
|
|
lang: params.lang,
|
|
noteId: params.noteId,
|
|
}),
|
|
signal: controller.signal,
|
|
})
|
|
} catch (err) {
|
|
clearTimeout(timeout)
|
|
const aborted = err instanceof Error && err.name === 'AbortError'
|
|
return {
|
|
ok: false,
|
|
error: aborted
|
|
? 'Génération trop longue — réessaie (ou raccourcis la note)'
|
|
: err instanceof Error
|
|
? err.message
|
|
: 'Network error',
|
|
}
|
|
} finally {
|
|
clearTimeout(timeout)
|
|
}
|
|
|
|
const data = await res.json().catch(() => ({}))
|
|
|
|
if (res.status === 402) {
|
|
return {
|
|
ok: false,
|
|
error: data.error || 'Quota exceeded',
|
|
quotaExceeded: true,
|
|
status: 402,
|
|
}
|
|
}
|
|
|
|
if (!res.ok) {
|
|
return {
|
|
ok: false,
|
|
error: data.error || `HTTP ${res.status}`,
|
|
issues: data.issues,
|
|
status: res.status,
|
|
}
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
demo: data.demo,
|
|
attempts: data.attempts ?? 1,
|
|
}
|
|
}
|