fix(audit): prototypes Gemini server-side + retire metrics-token du dépôt
Proxy Gemini côté serveur (plus de clé dans le bundle Vite), port prototype 4000, et suppression du token métriques placeholder versionné. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,7 +2,24 @@
|
||||
import { GoogleGenAI, Type } from "@google/genai";
|
||||
import { BrainstormIdea } from "../types";
|
||||
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
|
||||
async function generateContent(
|
||||
request: Parameters<InstanceType<typeof GoogleGenAI>['models']['generateContent']>[0],
|
||||
) {
|
||||
if (typeof window !== 'undefined') {
|
||||
const res = await fetch('/api/gemini/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
if (!res.ok) throw new Error('Gemini request failed');
|
||||
const data = await res.json();
|
||||
return { text: data.text ?? '' };
|
||||
}
|
||||
const key = process.env.GEMINI_API_KEY;
|
||||
if (!key) throw new Error('GEMINI_API_KEY required on server');
|
||||
const ai = new GoogleGenAI({ apiKey: key });
|
||||
return ai.models.generateContent(request);
|
||||
}
|
||||
|
||||
const BRAINSTORM_SCHEMA = {
|
||||
type: Type.OBJECT,
|
||||
@@ -63,7 +80,7 @@ export async function generateBrainstormWave(
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
||||
config: {
|
||||
@@ -101,7 +118,7 @@ export async function generateExpansion(parentIdeaTitle: string, parentIdeaDescr
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
||||
config: {
|
||||
@@ -130,9 +147,27 @@ export async function generateExpansion(parentIdeaTitle: string, parentIdeaDescr
|
||||
}
|
||||
}
|
||||
|
||||
async function embedContent(
|
||||
request: Parameters<InstanceType<typeof GoogleGenAI>['models']['embedContent']>[0],
|
||||
) {
|
||||
if (typeof window !== 'undefined') {
|
||||
const res = await fetch('/api/gemini/embed', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
if (!res.ok) throw new Error('Gemini embed failed');
|
||||
return res.json();
|
||||
}
|
||||
const key = process.env.GEMINI_API_KEY;
|
||||
if (!key) throw new Error('GEMINI_API_KEY required on server');
|
||||
const ai = new GoogleGenAI({ apiKey: key });
|
||||
return ai.models.embedContent(request);
|
||||
}
|
||||
|
||||
export async function getEmbedding(text: string): Promise<number[]> {
|
||||
try {
|
||||
const result = await ai.models.embedContent({
|
||||
const result = await embedContent({
|
||||
model: 'gemini-embedding-2-preview',
|
||||
contents: [text],
|
||||
});
|
||||
@@ -155,7 +190,7 @@ export function cosineSimilarity(a: number[], b: number[]): number {
|
||||
export async function nameCluster(noteSummaries: string[]): Promise<string> {
|
||||
const prompt = `Quel thème commun relie ces notes ? Donne un nom court (2-4 mots).\nNotes :\n${noteSummaries.join('\n- ')}`;
|
||||
try {
|
||||
const result = await ai.models.generateContent({
|
||||
const result = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: prompt
|
||||
});
|
||||
@@ -184,7 +219,7 @@ export async function suggestBridgeIdeas(
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: prompt,
|
||||
config: {
|
||||
@@ -207,7 +242,7 @@ export async function parseDocument(fileUrl: string, fileName: string): Promise<
|
||||
try {
|
||||
// In a real scenario, we would use media upload.
|
||||
// Here we simulate the extraction.
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
||||
config: {
|
||||
@@ -236,7 +271,7 @@ export async function extractActionItems(notes: { title: string; content: string
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3-flash-preview",
|
||||
contents: prompt,
|
||||
config: {
|
||||
@@ -289,7 +324,7 @@ export async function generateFlashcardsForNote(
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await ai.models.generateContent({
|
||||
const response = await generateContent({
|
||||
model: "gemini-3.5-flash",
|
||||
contents: [{ role: "user", parts: [{ text: prompt }] }],
|
||||
config: {
|
||||
|
||||
Reference in New Issue
Block a user