Checkpoint: Implémentation du résumé automatique généré par l'IA pour chaque article RSS (veille et AAP), marquage lu/non lu avec point bleu et fond teinté, bouton "Tout marquer comme lu", compteurs non lus dans la sidebar et dans les titres de page. Migration BDD : table article_reads + colonne iaResume dans veille_items et aap_items.

This commit is contained in:
Manus
2026-06-16 03:08:29 -04:00
parent c47c76215e
commit 67dfbb1a13
12 changed files with 1324 additions and 35 deletions

View File

@@ -22,7 +22,7 @@ import {
type RssFeed,
} from "../drizzle/schema";
import { eq, sql } from "drizzle-orm";
import { classifyArticle } from "./aiClassifier";
import { classifyArticle, generateSummary } from "./aiClassifier";
// ─── Types internes ───────────────────────────────────────────────────────────
@@ -371,6 +371,11 @@ async function processFeed(feed: RssFeed): Promise<FetchResult> {
const typeVeille = (aiResult.typeVeille ?? feed.defaultTypeVeille ?? "generale") as
"reglementaire" | "concurrentielle" | "technologique" | "generale";
// Générer le résumé IA uniquement pour les articles pertinents
const iaResume = aiResult.relevant
? await generateSummary(title, description)
: null;
try {
// Essayer d'insérer
await db.insert(veilleItems).values({
@@ -389,6 +394,7 @@ async function processFeed(feed: RssFeed): Promise<FetchResult> {
iaCategorie: aiResult.categorie,
iaClassifiedBy: aiResult.classifiedBy,
iaReason: aiResult.reason,
iaResume: iaResume || null,
});
result.newItems++;
} catch (e: any) {
@@ -434,6 +440,11 @@ async function processFeed(feed: RssFeed): Promise<FetchResult> {
const categorie = aiResult.categorie as
"Handicap" | "PA" | "Enfance" | "Précarité" | "Sanitaire" | "Autre";
// Générer le résumé IA uniquement pour les articles pertinents
const iaResume = aiResult.relevant
? await generateSummary(title, description)
: null;
try {
await db.insert(aapItems).values({
dedupKey,
@@ -448,6 +459,7 @@ async function processFeed(feed: RssFeed): Promise<FetchResult> {
iaCategorie: aiResult.categorie,
iaClassifiedBy: aiResult.classifiedBy,
iaReason: aiResult.reason,
iaResume: iaResume || null,
});
result.newItems++;
} catch (e: any) {