Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/app.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import type { AuthRequest, Session } from 'lucia';
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
interface Error {
message: string;
carlosContext?: {
prompt: string;
};
}
interface Locals {
db: PrismaClient;
auth: AuthRequest;
Expand Down
17 changes: 17 additions & 0 deletions src/error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
<meta name="robots" content="noindex" />
<meta name="googlebot" content="noindex" />
<title>%sveltekit.status% - %sveltekit.error.message%</title>
<meta name="description" content="Une page que personne ne devrait voir." />
</head>
<body style="display: flex; margin: 0; flex-direction: column; gap: 2rem; width: 100vw; height: 100vh; align-items: center; justify-content: center;">
<h1>%sveltekit.status% - %sveltekit.error.message%</h1>
<p>Quelque chose s'est très très mal passé. Nous sommes désolés pour la gêne occasionnée.</p>
<a href="/">Retour à l'accueil</a>
</body>
</html>
28 changes: 27 additions & 1 deletion src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { CARLOS_DEFAULT_ERROR_PROMPT, CARLOS_ERROR_PROMPT } from '$lib/server/GPT';
import { auth } from '$lib/server/auth';
import { db } from '$lib/server/db';

import type { Handle } from '@sveltejs/kit';
import type { Handle, HandleServerError } from '@sveltejs/kit';

const ERROR_MESSAGE: Record<'404' | '500' | string, string> = {
404: "La page demandée n'existe pas.",
500: 'Le serveur a rencontré un problème.',
};

export const handle: Handle = async ({ event, resolve }) => {
event.locals.db = db;
Expand All @@ -10,3 +16,23 @@ export const handle: Handle = async ({ event, resolve }) => {

return resolve(event);
};

export const handleError: HandleServerError = async ({ message, status, error }) => {
if (status >= 500) {
// eslint-disable-next-line no-console
console.log(`Unhandled error "${message}" with status ${status}:`, error);
}

let prompt = `L'utilisateur se trouve actuellement sur une page d'erreur ${status}.`;

if (CARLOS_ERROR_PROMPT[status.toString()]) {
prompt += CARLOS_ERROR_PROMPT[status.toString()];
}

prompt += CARLOS_DEFAULT_ERROR_PROMPT;

return {
message: ERROR_MESSAGE[status.toString()] || message,
carlosContext: { prompt },
};
};
5 changes: 3 additions & 2 deletions src/lib/components/Assistant.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
];

const context = {
prompt: $page.data.carlosContext?.prompt,
prompt: $page.data.carlosContext?.prompt ?? $page.error?.carlosContext?.prompt,
};

abortController = new AbortController();
Expand Down Expand Up @@ -217,7 +217,8 @@
containerClass="border-2 border-primary-700"
innerContainerClass="sm:min-h-[50vh] min-h-[55vh] flex flex-col"
>
{@const carlosHasContext = $page.data.carlosContext?.prompt}
{@const carlosHasContext =
$page.data.carlosContext?.prompt ?? $page.error?.carlosContext?.prompt}

<div class="flex justify-between items-start">
<div class="grid sm:flex gap-2.5 items-center">
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/Pagination.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
flex items-center justify-center px-4 h-10 leading-tight text-gray-500 bg-white border border-gray-300
hover:bg-gray-100 hover:text-gray-700 focus-visible:bg-gray-100 focus-visible:text-gray-700
"
href={getUrlForPage(totalPages)}
href={getUrlForPage(nextPage)}
>
<Forward aria-hidden="true" />
</a>
Expand Down
15 changes: 15 additions & 0 deletions src/lib/server/GPT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@ import OpenAI from 'openai';

import { OPENAI_API_KEY } from '$env/static/private';

export const CARLOS_DEFAULT_ERROR_PROMPT = `
Ton but est d'aider l'utilisateur à résoudre son problème.
Indique à l'utilisateur qu'il peut retourner sur la page d'accueil en cliquant sur le bouton "Retour à l'accueil".
`;
export const CARLOS_ERROR_PROMPT: Record<'404' | '500' | string, string> = {
404: `
Si l'utilisateur te sollicite, indique lui que la page demandée n'existe pas.
Demande à l'utilisateur de vérifier l'URL ou de retourner sur la page d'accueil.
`,
500: `
Si l'utilisateur te sollicite, indique lui que le serveur a rencontré un problème.
Demande à l'utilisateur de réessayer plus tard ou de retourner sur la page d'accueil.
`,
};

export const openai = new OpenAI({
apiKey: OPENAI_API_KEY,
});
42 changes: 42 additions & 0 deletions src/routes/+error.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { assistantOpen } from '$lib/stores/assistant';

import { page } from '$app/stores';
</script>

<svelte:head>
<title>{$page.status}</title>
<meta name="description" content={$page.error?.message ?? 'Une erreur est survenue.'} />
<meta name="robots" content="noindex" />
<meta name="googlebot" content="noindex" />
</svelte:head>

<section>
<div class="py-8 px-4 mx-auto max-w-screen-xl lg:py-16 lg:px-6">
<div class="mx-auto max-w-screen-sm text-center">
<h1 class="mb-4 text-7xl tracking-tight font-extrabold lg:text-9xl text-primary-600">
{$page.status}
</h1>
<p class="mb-4 text-lg font-light text-gray-500">
{$page.error?.message ?? 'Une erreur est survenue.'}
</p>
<p class="mb-4 text-lg font-light text-gray-800">
Besoin d'aide ? <button
type="button"
class="text-primary-700 hover:text-primary-800 focus-visible:text-primary-800 transition-colors motion-reduce:transition-none"
aria-label="Carlos (ouvrir l'assistant)"
aria-haspopup="dialog"
on:click={() => {
$assistantOpen = true;
}}>Carlos</button
> peut vous aider.
</p>
<a
href="/"
class="inline-flex text-white bg-primary-600 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center my-4"
>
Retour à l'accueil
</a>
</div>
</div>
</section>
20 changes: 17 additions & 3 deletions src/routes/recipes/[slug]/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import { error } from '@sveltejs/kit';
import { error, redirect } from '@sveltejs/kit';

import { CARLOS_DEFAULT_ERROR_PROMPT } from '$lib/server/GPT';

import type { LayoutServerLoad } from './$types';

export const load = (async ({ params, locals }) => {
const { db } = locals;
export const load = (async ({ locals, params }) => {
const { db, session } = locals;

if (!session) {
redirect(303, '/login');
}

try {
const recipe = await db.recipe.findUniqueOrThrow({
Expand All @@ -21,6 +27,14 @@ export const load = (async ({ params, locals }) => {
if (e.code === 'P2025') {
error(404, {
message: "Cette recette n'existe pas.",
carlosContext: {
prompt: `
L'utilisateur se trouve actuellement sur une page d'erreur 404.
Si l'utilisateur te sollicite, indique lui que la recette demandée n'existe pas.
Demande à l'utilisateur de vérifier l'URL ou de retourner sur la page d'accueil.
${CARLOS_DEFAULT_ERROR_PROMPT}
`,
},
});
}
}
Expand Down