From 0be3e8c564f7caf5edbc79fe39b3cb617cc59e66 Mon Sep 17 00:00:00 2001 From: Alex Patterson Date: Thu, 5 Mar 2026 14:08:36 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20migrate=20@google/generative-ai=20?= =?UTF-8?q?=E2=86=92=20@google/genai=20+=20add=20Deep=20Research=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task 1 — SDK Migration: - Replace @google/generative-ai with @google/genai in package.json - lib/gemini.ts: lazy-init GoogleGenAI client, ai.models.generateContent() - lib/sponsor/gemini-intent.ts: migrate to new SDK API surface - lib/sponsor/gemini-outreach.ts: migrate to new SDK API surface - response.text is now a property (not method) in new SDK Task 2 — Deep Research Config: - pipelineConfig.ts: add enableDeepResearch, deepResearchAgent, deepResearchPromptTemplate, infographicModel fields - lib/types/config.ts: add matching PipelineConfig interface fields --- lib/gemini.ts | 23 +++++++++++----- lib/sponsor/gemini-intent.ts | 17 +++++------- lib/sponsor/gemini-outreach.ts | 17 +++++------- lib/types/config.ts | 4 +++ package.json | 2 +- sanity/schemas/singletons/pipelineConfig.ts | 30 ++++++++++++++++++++- 6 files changed, 64 insertions(+), 29 deletions(-) diff --git a/lib/gemini.ts b/lib/gemini.ts index 0e3110da..7a30697f 100644 --- a/lib/gemini.ts +++ b/lib/gemini.ts @@ -1,7 +1,16 @@ -import { GoogleGenerativeAI } from "@google/generative-ai"; +import { GoogleGenAI } from "@google/genai"; import { getConfigValue } from "@/lib/config"; -const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY || ""); +let _ai: GoogleGenAI | null = null; + +/** Lazy-initialize the GoogleGenAI client (avoids crash at import time if GEMINI_API_KEY is missing). */ +function getAI(): GoogleGenAI { + if (!_ai) { + const apiKey = process.env.GEMINI_API_KEY || ""; + _ai = new GoogleGenAI({ apiKey }); + } + return _ai; +} /** * Generate text content using Gemini Flash. @@ -14,13 +23,13 @@ export async function generateWithGemini( systemInstruction?: string, ): Promise { const geminiModel = await getConfigValue("pipeline_config", "geminiModel", "gemini-2.0-flash"); - const model = genAI.getGenerativeModel({ + const ai = getAI(); + const response = await ai.models.generateContent({ model: geminiModel, - ...(systemInstruction && { systemInstruction }), + contents: prompt, + ...(systemInstruction && { config: { systemInstruction } }), }); - const result = await model.generateContent(prompt); - const response = result.response; - return response.text(); + return response.text ?? ""; } /** diff --git a/lib/sponsor/gemini-intent.ts b/lib/sponsor/gemini-intent.ts index 9a9024d4..8c816d8d 100644 --- a/lib/sponsor/gemini-intent.ts +++ b/lib/sponsor/gemini-intent.ts @@ -1,4 +1,4 @@ -import { GoogleGenerativeAI } from '@google/generative-ai' +import { GoogleGenAI } from '@google/genai' import { getConfigValue } from '@/lib/config' const SPONSORSHIP_TIERS = [ @@ -17,10 +17,6 @@ export interface SponsorIntent { urgency: 'low' | 'medium' | 'high' } -/** - * Uses Gemini Flash to parse inbound sponsor emails/messages - * and extract structured data for creating a sponsorLead. - */ export async function extractSponsorIntent(message: string): Promise { const apiKey = process.env.GEMINI_API_KEY if (!apiKey) { @@ -35,8 +31,7 @@ export async function extractSponsorIntent(message: string): Promise