chore: supprime les derniers restes de l'IA dans les Paramètres

La section « IA Copilot — OpenRouter » annonçait « pour les analyses de
gammes », mais aucun code ne consommait cette clé : elle était décorative.
Supprimée, ainsi que les routes devenues orphelines /api/admin/ai-config,
/api/google-ai/models et /api/openrouter/models.

Nettoyage de l'état correspondant dans la page : clé, liste de modèles,
fournisseur d'IA et modèle Google ne faisaient plus qu'un aller-retour entre le
chargement et l'enregistrement, sans aucune interface pour les modifier.
handleSave n'enregistre donc plus que l'URL de la base.

La règle set-state-in-effect s'est mise à signaler le `setIsMounted` du montage,
inchangé mais devenu analysable une fois le code IA retiré : dérogation locale,
comme dans api-connection-info.tsx, puisque poser l'indicateur au montage est
précisément ce qui évite l'écart d'hydratation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y26nRZxTR57K7h8yqsF675
This commit is contained in:
Claude committed 2026-08-07 07:06:23 +00:00
1 parent fff4cd9641
commit be8d576af5
6 files changed
+456 -242

No files matched your search

-24
View File
@@ -1,24 +0,0 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import fs from "fs/promises";
import path from "path";
export async function GET() {
const session = await auth();
if (!session || (session.user as any)?.role !== "admin") {
return NextResponse.json({ error: "Unauthorized" }, { status: 403 });
}
try {
const configFile = path.join(process.cwd(), "data", ".db-config.json");
const data = await fs.readFile(configFile, "utf-8");
const config = JSON.parse(data);
return NextResponse.json({
provider: config.aiProvider ?? "openrouter",
openRouterModel: config.openRouterModel,
googleAiModel: config.googleAiModel,
});
} catch {
return NextResponse.json({ provider: "openrouter" });
}
}
-61
View File
@@ -1,61 +0,0 @@
import { NextRequest, NextResponse } from "next/server";
import fs from "fs/promises";
import path from "path";
async function getSavedGoogleKey(): Promise<string | null> {
try {
const configFile = path.join(process.cwd(), "data", ".db-config.json");
const data = await fs.readFile(configFile, "utf-8");
const config = JSON.parse(data);
return config.googleAiKey ?? null;
} catch {
return null;
}
}
export async function GET(req: NextRequest) {
const apiKey = req.headers.get("x-google-ai-key")
|| process.env.GOOGLE_AI_KEY
|| await getSavedGoogleKey();
if (!apiKey) {
return NextResponse.json({ error: "No Google AI key provided" }, { status: 401 });
}
try {
const res = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}&pageSize=100`,
{ cache: "no-store" }
);
if (!res.ok) {
const err = await res.text();
return NextResponse.json({ error: err }, { status: res.status });
}
const data = await res.json();
// Keep only generative models that support generateContent
const models = (data.models as Array<{
name: string;
displayName: string;
supportedGenerationMethods?: string[];
description?: string;
}>)
.filter(m =>
m.supportedGenerationMethods?.includes("generateContent") &&
!m.name.includes("embedding") &&
!m.name.includes("aqa")
)
.map(m => ({
id: m.name.replace("models/", ""),
name: m.displayName,
}))
.sort((a, b) => a.name.localeCompare(b.name, "fr"));
return NextResponse.json({ models });
} catch (err) {
const msg = err instanceof Error ? err.message : "Unknown error";
return NextResponse.json({ error: msg }, { status: 500 });
}
}
-61
View File
@@ -1,61 +0,0 @@
import { NextRequest, NextResponse } from "next/server";
import fs from "fs/promises";
import path from "path";
async function getSavedOpenRouterKey(): Promise<string | null> {
try {
const configFile = path.join(process.cwd(), "data", ".db-config.json");
const data = await fs.readFile(configFile, "utf-8");
const config = JSON.parse(data);
return config.openRouterKey ?? null;
} catch {
return null;
}
}
export async function GET(req: NextRequest) {
const apiKey = req.headers.get("x-openrouter-key")
|| process.env.OPENROUTER_API_KEY
|| await getSavedOpenRouterKey();
if (!apiKey) {
return NextResponse.json({ error: "No API key provided" }, { status: 401 });
}
try {
const res = await fetch("https://openrouter.ai/api/v1/models", {
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
cache: "no-store",
});
if (!res.ok) {
return NextResponse.json({ error: "OpenRouter error", status: res.status }, { status: res.status });
}
const data = await res.json();
// Return simplified list sorted by name
const models = (data.data as Array<{ id: string; name: string; pricing?: { prompt: string; completion: string } }>)
.map((m) => ({
id: m.id,
name: m.name,
promptPrice: parseFloat(m.pricing?.prompt ?? "0"),
completionPrice: parseFloat(m.pricing?.completion ?? "0"),
free: parseFloat(m.pricing?.prompt ?? "1") === 0,
}))
.sort((a, b) => {
// Free models first, then alphabetical
if (a.free && !b.free) return -1;
if (!a.free && b.free) return 1;
return a.name.localeCompare(b.name, "fr");
});
return NextResponse.json({ models });
} catch (err) {
const msg = err instanceof Error ? err.message : "Unknown error";
return NextResponse.json({ error: msg }, { status: 500 });
}
}