Refactor app flows and refresh UI components

This commit is contained in:
Jacques_tirot
2026-09-08 14:20:23 +02:00
parent 4e14a38d4e
commit 814e1d27fb
71 changed files with 1984 additions and 509 deletions
+76 -31
View File
@@ -7,8 +7,46 @@ const { setTimeout } = require('timers/promises')
// --- CONFIGURATION ---
// Plus intelligente que le Flash original, ultra rapide, et stable sur l'API.
const TEXT_MODEL_NAME = 'gemini-flash-latest'
const TEXT_MODEL_NAME = 'gemini-3.5-flash'
const TEXT_FALLBACK_MODEL_NAME = 'gemini-3.1-flash-lite'
const IMAGE_MODEL_NAME = 'gemini-3-pro-image'
const TEXT_GENERATION_MAX_ATTEMPTS = 3
const TEXT_GENERATION_RETRY_DELAY_MS = 1000
const isRetryableTextGenerationError = (error) => {
const status = Number(error?.status || error?.response?.status)
return [429, 500, 502, 503, 504].includes(status)
}
const generateTextWithRetry = async (ai, request, operation) => {
let lastError = null
for (let attempt = 1; attempt <= TEXT_GENERATION_MAX_ATTEMPTS; attempt += 1) {
const modelName =
attempt === TEXT_GENERATION_MAX_ATTEMPTS ? TEXT_FALLBACK_MODEL_NAME : TEXT_MODEL_NAME
try {
return await ai.generate({
...request,
model: googleAI.model(modelName),
})
} catch (error) {
lastError = error
const shouldRetry =
isRetryableTextGenerationError(error) && attempt < TEXT_GENERATION_MAX_ATTEMPTS
if (!shouldRetry) throw error
const delayMs = TEXT_GENERATION_RETRY_DELAY_MS * 2 ** (attempt - 1)
console.warn(
`🔄 [${operation}] ${modelName} indisponible (${error?.status || 'réseau'}), nouvelle tentative ${attempt + 1}/${TEXT_GENERATION_MAX_ATTEMPTS} dans ${delayMs}ms`
)
await setTimeout(delayMs)
}
}
throw lastError
}
// --- SINGLETON PATTERN (WARM START) ---
// On stocke l'instance en dehors de la fonction pour la réutiliser
@@ -39,15 +77,18 @@ exports.generateAI = async ({ system = '', prompt = '', schema }) => {
const startedAt = Date.now()
try {
const { output } = await ai.generate({
model: googleAI.model(TEXT_MODEL_NAME),
system,
prompt,
output: { schema },
config: {
temperature: 0.7, // Créativité équilibrée
const { output } = await generateTextWithRetry(
ai,
{
system,
prompt,
output: { schema },
config: {
temperature: 0.7, // Créativité équilibrée
},
},
})
'generateAI'
)
return output
} catch (error) {
@@ -97,7 +138,7 @@ exports.analyseLyrics = async ({ title = '', lyrics }) => {
flagged: z.boolean().describe('Vrai si le contenu nécessite un avertissement.'),
blocked: z.boolean().describe('Vrai UNIQUEMENT si violation grave (Haine, Violence réelle).'),
score: z.number().min(0).max(1).describe('Score de risque (0=Sûr, 1=Dangereux).'),
reasons: z.array(z.string()).describe('Liste concise des raisons.'),
reasons: z.array(z.string()).max(5).describe('Liste concise des raisons.'),
excerpts: z
.array(
z.object({
@@ -106,7 +147,7 @@ exports.analyseLyrics = async ({ title = '', lyrics }) => {
severity: z.string(),
})
)
.max(10),
.max(3),
success: z.boolean(),
})
@@ -133,27 +174,31 @@ ${lyricsText}
const startedAt = Date.now()
try {
const { output } = await ai.generate({
model: googleAI.model(TEXT_MODEL_NAME),
system,
prompt: userPrompt,
output: { schema: moderationSchema },
config: {
// Paramètres de sécurité permissifs pour laisser l'IA voir et juger le contenu
safetySettings: [
{ category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_NONE' },
{
category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
threshold: 'BLOCK_NONE',
},
{
category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
threshold: 'BLOCK_NONE',
},
{ category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_NONE' },
],
const { output } = await generateTextWithRetry(
ai,
{
system,
prompt: userPrompt,
output: { schema: moderationSchema },
config: {
temperature: 0,
// Paramètres de sécurité permissifs pour laisser l'IA voir et juger le contenu
safetySettings: [
{ category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_NONE' },
{
category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
threshold: 'BLOCK_NONE',
},
{
category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
threshold: 'BLOCK_NONE',
},
{ category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_NONE' },
],
},
},
})
'analyseLyrics'
)
if (!output) throw new Error("Échec de l'analyse de modération.")