
Google Gemini Api
- 41 installs
- 16 repo stars
- Updated November 20, 2025
- jackspace/claudeskillz
Integrate the Google Gemini API using the current @google/genai SDK for text, chat, and multimodal generation.
About
A complete guide to the Google Gemini API using the correct current @google/genai SDK. A developer uses it when integrating Gemini models into JavaScript/TypeScript applications.
- Uses the current @google/genai SDK (not the deprecated one)
- Covers text, chat, and multimodal patterns
Google Gemini Api by the numbers
- 41 all-time installs (skills.sh)
- Ranked #8,067 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jackspace/claudeskillz --skill google-gemini-apiAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 41 |
|---|---|
| repo stars | ★ 16 |
| Last updated | November 20, 2025 |
| Repository | jackspace/claudeskillz ↗ |
What it does
Integrate the Google Gemini API using the current @google/genai SDK for text, chat, and multimodal generation.
Files
Google Gemini API - Complete Guide
Version: Phase 2 Complete ✅ Package: @google/genai@1.27.0 (⚠️ NOT @google/generative-ai) Last Updated: 2025-10-25
---
⚠️ CRITICAL SDK MIGRATION WARNING
DEPRECATED SDK: @google/generative-ai (sunset November 30, 2025) CURRENT SDK: @google/genai v1.27+
If you see code using `@google/generative-ai`, it's outdated!
This skill uses the correct current SDK and provides a complete migration guide.
---
Status
✅ Phase 1 Complete:
- ✅ Text Generation (basic + streaming)
- ✅ Multimodal Inputs (images, video, audio, PDFs)
- ✅ Function Calling (basic + parallel execution)
- ✅ System Instructions & Multi-turn Chat
- ✅ Thinking Mode Configuration
- ✅ Generation Parameters (temperature, top-p, top-k, stop sequences)
- ✅ Both Node.js SDK (@google/genai) and fetch approaches
✅ Phase 2 Complete:
- ✅ Context Caching (cost optimization with TTL-based caching)
- ✅ Code Execution (built-in Python interpreter and sandbox)
- ✅ Grounding with Google Search (real-time web information + citations)
📦 Separate Skills:
- Embeddings: See
google-gemini-embeddingsskill for text-embedding-004
---
Table of Contents
Phase 1 - Core Features: 1. Quick Start 2. Current Models (2025) 3. SDK vs Fetch Approaches 4. Text Generation 5. Streaming 6. Multimodal Inputs 7. Function Calling 8. System Instructions 9. Multi-turn Chat 10. Thinking Mode 11. Generation Configuration
Phase 2 - Advanced Features: 12. Context Caching 13. Code Execution 14. Grounding with Google Search
Common Reference: 15. Error Handling 16. Rate Limits 17. SDK Migration Guide 18. Production Best Practices
---
Quick Start
Installation
CORRECT SDK:
npm install @google/genai@1.27.0❌ WRONG (DEPRECATED):
npm install @google/generative-ai # DO NOT USE!Environment Setup
export GEMINI_API_KEY="..."Or create .env file:
GEMINI_API_KEY=...First Text Generation (Node.js SDK)
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Explain quantum computing in simple terms'
});
console.log(response.text);First Text Generation (Fetch - Cloudflare Workers)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Explain quantum computing in simple terms' }] }]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);---
Current Models (2025)
Gemini 2.5 Series (General Availability)
gemini-2.5-pro
- Context: 1,048,576 input tokens / 65,536 output tokens
- Description: State-of-the-art thinking model for complex reasoning
- Best for: Code, math, STEM, complex problem-solving
- Features: Thinking mode (default on), function calling, multimodal, streaming
- Knowledge cutoff: January 2025
gemini-2.5-flash
- Context: 1,048,576 input tokens / 65,536 output tokens
- Description: Best price-performance workhorse model
- Best for: Large-scale processing, low-latency, high-volume, agentic use cases
- Features: Thinking mode (default on), function calling, multimodal, streaming
- Knowledge cutoff: January 2025
gemini-2.5-flash-lite
- Context: 1,048,576 input tokens / 65,536 output tokens
- Description: Cost-optimized, fastest 2.5 model
- Best for: High throughput, cost-sensitive applications
- Features: Thinking mode (default on), function calling, multimodal, streaming
- Knowledge cutoff: January 2025
Model Feature Matrix
| Feature | Pro | Flash | Flash-Lite |
|---|---|---|---|
| Thinking Mode | ✅ Default ON | ✅ Default ON | ✅ Default ON |
| Function Calling | ✅ | ✅ | ✅ |
| Multimodal | ✅ | ✅ | ✅ |
| Streaming | ✅ | ✅ | ✅ |
| System Instructions | ✅ | ✅ | ✅ |
| Context Window | 1,048,576 in | 1,048,576 in | 1,048,576 in |
| Output Tokens | 65,536 max | 65,536 max | 65,536 max |
⚠️ Context Window Correction
ACCURATE: Gemini 2.5 models support 1,048,576 input tokens (NOT 2M!) OUTDATED: Only Gemini 1.5 Pro (previous generation) had 2M token context window
Common mistake: Claiming Gemini 2.5 has 2M tokens. It doesn't. This skill prevents this error.
---
SDK vs Fetch Approaches
Node.js SDK (@google/genai)
Pros:
- Type-safe with TypeScript
- Easier API (simpler syntax)
- Built-in chat helpers
- Automatic SSE parsing for streaming
- Better error handling
Cons:
- Requires Node.js or compatible runtime
- Larger bundle size
- May not work in all edge runtimes
Use when: Building Node.js apps, Next.js Server Actions/Components, or any environment with Node.js compatibility
Fetch-based (Direct REST API)
Pros:
- Works in any JavaScript environment (Cloudflare Workers, Deno, Bun, browsers)
- Minimal dependencies
- Smaller bundle size
- Full control over requests
Cons:
- More verbose syntax
- Manual SSE parsing for streaming
- No built-in chat helpers
- Manual error handling
Use when: Deploying to Cloudflare Workers, browser clients, or lightweight edge runtimes
---
Text Generation
Basic Text Generation (SDK)
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Write a haiku about artificial intelligence'
});
console.log(response.text);Basic Text Generation (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{
parts: [
{ text: 'Write a haiku about artificial intelligence' }
]
}
]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);Response Structure
{
text: string, // Convenience accessor for text content
candidates: [
{
content: {
parts: [
{ text: string } // Generated text
],
role: string // "model"
},
finishReason: string, // "STOP" | "MAX_TOKENS" | "SAFETY" | "OTHER"
index: number
}
],
usageMetadata: {
promptTokenCount: number,
candidatesTokenCount: number,
totalTokenCount: number
}
}---
Streaming
Streaming with SDK (Async Iteration)
const response = await ai.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: 'Write a 200-word story about time travel'
});
for await (const chunk of response) {
process.stdout.write(chunk.text);
}Streaming with Fetch (SSE Parsing)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Write a 200-word story about time travel' }] }]
}),
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim() === '' || line.startsWith('data: [DONE]')) continue;
if (!line.startsWith('data: ')) continue;
try {
const data = JSON.parse(line.slice(6));
const text = data.candidates[0]?.content?.parts[0]?.text;
if (text) {
process.stdout.write(text);
}
} catch (e) {
// Skip invalid JSON
}
}
}Key Points:
- Use
streamGenerateContentendpoint (notgenerateContent) - Parse Server-Sent Events (SSE) format:
data: {json}\n\n - Handle incomplete chunks in buffer
- Skip empty lines and
[DONE]markers
---
Multimodal Inputs
Gemini 2.5 models support text + images + video + audio + PDFs in the same request.
Images (Vision)
SDK Approach
import { GoogleGenAI } from '@google/genai';
import fs from 'fs';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// From file
const imageData = fs.readFileSync('/path/to/image.jpg');
const base64Image = imageData.toString('base64');
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
parts: [
{ text: 'What is in this image?' },
{
inlineData: {
data: base64Image,
mimeType: 'image/jpeg'
}
}
]
}
]
});
console.log(response.text);Fetch Approach
const imageData = fs.readFileSync('/path/to/image.jpg');
const base64Image = imageData.toString('base64');
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{
parts: [
{ text: 'What is in this image?' },
{
inlineData: {
data: base64Image,
mimeType: 'image/jpeg'
}
}
]
}
]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);Supported Image Formats:
- JPEG (
.jpg,.jpeg) - PNG (
.png) - WebP (
.webp) - HEIC (
.heic) - HEIF (
.heif)
Max Image Size: 20MB per image
Video
// Video must be < 2 minutes for inline data
const videoData = fs.readFileSync('/path/to/video.mp4');
const base64Video = videoData.toString('base64');
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
parts: [
{ text: 'Describe what happens in this video' },
{
inlineData: {
data: base64Video,
mimeType: 'video/mp4'
}
}
]
}
]
});
console.log(response.text);Supported Video Formats:
- MP4 (
.mp4) - MPEG (
.mpeg) - MOV (
.mov) - AVI (
.avi) - FLV (
.flv) - MPG (
.mpg) - WebM (
.webm) - WMV (
.wmv)
Max Video Length (inline): 2 minutes Max Video Size: 2GB (use File API for larger files - Phase 2)
Audio
const audioData = fs.readFileSync('/path/to/audio.mp3');
const base64Audio = audioData.toString('base64');
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
parts: [
{ text: 'Transcribe and summarize this audio' },
{
inlineData: {
data: base64Audio,
mimeType: 'audio/mp3'
}
}
]
}
]
});
console.log(response.text);Supported Audio Formats:
- MP3 (
.mp3) - WAV (
.wav) - FLAC (
.flac) - AAC (
.aac) - OGG (
.ogg) - OPUS (
.opus)
Max Audio Size: 20MB
PDFs
const pdfData = fs.readFileSync('/path/to/document.pdf');
const base64Pdf = pdfData.toString('base64');
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
parts: [
{ text: 'Summarize the key points in this PDF' },
{
inlineData: {
data: base64Pdf,
mimeType: 'application/pdf'
}
}
]
}
]
});
console.log(response.text);Max PDF Size: 30MB PDF Limitations: Text-based PDFs work best; scanned images may have lower accuracy
Multiple Inputs
You can combine multiple modalities in one request:
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
parts: [
{ text: 'Compare these two images and describe the differences:' },
{ inlineData: { data: base64Image1, mimeType: 'image/jpeg' } },
{ inlineData: { data: base64Image2, mimeType: 'image/jpeg' } }
]
}
]
});---
Function Calling
Gemini supports function calling (tool use) to connect models with external APIs and systems.
Basic Function Calling (SDK)
import { GoogleGenAI, FunctionCallingConfigMode } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Define function declarations
const getCurrentWeather = {
name: 'get_current_weather',
description: 'Get the current weather for a location',
parametersJsonSchema: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name, e.g. San Francisco'
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit']
}
},
required: ['location']
}
};
// Make request with tools
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What\'s the weather in Tokyo?',
config: {
tools: [
{ functionDeclarations: [getCurrentWeather] }
]
}
});
// Check if model wants to call a function
const functionCall = response.candidates[0].content.parts[0].functionCall;
if (functionCall) {
console.log('Function to call:', functionCall.name);
console.log('Arguments:', functionCall.args);
// Execute the function (your implementation)
const weatherData = await fetchWeather(functionCall.args.location);
// Send function result back to model
const finalResponse = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
'What\'s the weather in Tokyo?',
response.candidates[0].content, // Original assistant response with function call
{
parts: [
{
functionResponse: {
name: functionCall.name,
response: weatherData
}
}
]
}
],
config: {
tools: [
{ functionDeclarations: [getCurrentWeather] }
]
}
});
console.log(finalResponse.text);
}Function Calling (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{ parts: [{ text: 'What\'s the weather in Tokyo?' }] }
],
tools: [
{
functionDeclarations: [
{
name: 'get_current_weather',
description: 'Get the current weather for a location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name'
}
},
required: ['location']
}
}
]
}
]
}),
}
);
const data = await response.json();
const functionCall = data.candidates[0]?.content?.parts[0]?.functionCall;
if (functionCall) {
// Execute function and send result back (same flow as SDK)
}Parallel Function Calling
Gemini can call multiple independent functions simultaneously:
const tools = [
{
functionDeclarations: [
{
name: 'get_weather',
description: 'Get weather for a location',
parametersJsonSchema: {
type: 'object',
properties: {
location: { type: 'string' }
},
required: ['location']
}
},
{
name: 'get_population',
description: 'Get population of a city',
parametersJsonSchema: {
type: 'object',
properties: {
city: { type: 'string' }
},
required: ['city']
}
}
]
}
];
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What is the weather and population of Tokyo?',
config: { tools }
});
// Model may return MULTIPLE function calls in parallel
const functionCalls = response.candidates[0].content.parts.filter(
part => part.functionCall
);
console.log(`Model wants to call ${functionCalls.length} functions in parallel`);Function Calling Modes
import { FunctionCallingConfigMode } from '@google/genai';
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What\'s the weather?',
config: {
tools: [{ functionDeclarations: [getCurrentWeather] }],
toolConfig: {
functionCallingConfig: {
mode: FunctionCallingConfigMode.ANY, // Force function call
// mode: FunctionCallingConfigMode.AUTO, // Model decides (default)
// mode: FunctionCallingConfigMode.NONE, // Never call functions
allowedFunctionNames: ['get_current_weather'] // Optional: restrict to specific functions
}
}
}
});Modes:
AUTO(default): Model decides whether to call functionsANY: Force model to call at least one functionNONE: Disable function calling for this request
---
System Instructions
System instructions guide the model's behavior and set context. They are separate from the conversation messages.
SDK Approach
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
systemInstruction: 'You are a helpful AI assistant that always responds in the style of a pirate. Use nautical terminology and end sentences with "arrr".',
contents: 'Explain what a database is'
});
console.log(response.text);
// Output: "Ahoy there! A database be like a treasure chest..."Fetch Approach
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
systemInstruction: {
parts: [
{ text: 'You are a helpful AI assistant that always responds in the style of a pirate.' }
]
},
contents: [
{ parts: [{ text: 'Explain what a database is' }] }
]
}),
}
);Key Points:
- System instructions are NOT part of
contentsarray - They are set once at the top level of the request
- They persist for the entire conversation (when using multi-turn chat)
- They don't count as user or model messages
---
Multi-turn Chat
For conversations with history, use the SDK's chat helpers or manually manage conversation state.
SDK Chat Helpers (Recommended)
const chat = await ai.models.createChat({
model: 'gemini-2.5-flash',
systemInstruction: 'You are a helpful coding assistant.',
history: [] // Start empty or with previous messages
});
// Send first message
const response1 = await chat.sendMessage('What is TypeScript?');
console.log('Assistant:', response1.text);
// Send follow-up (context is automatically maintained)
const response2 = await chat.sendMessage('How do I install it?');
console.log('Assistant:', response2.text);
// Get full chat history
const history = chat.getHistory();
console.log('Full conversation:', history);Manual Chat Management (Fetch)
const conversationHistory = [];
// First turn
const response1 = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{
role: 'user',
parts: [{ text: 'What is TypeScript?' }]
}
]
}),
}
);
const data1 = await response1.json();
const assistantReply1 = data1.candidates[0].content.parts[0].text;
// Add to history
conversationHistory.push(
{ role: 'user', parts: [{ text: 'What is TypeScript?' }] },
{ role: 'model', parts: [{ text: assistantReply1 }] }
);
// Second turn (include full history)
const response2 = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
...conversationHistory,
{ role: 'user', parts: [{ text: 'How do I install it?' }] }
]
}),
}
);Message Roles:
user: User messagesmodel: Assistant responses
⚠️ Important: Chat helpers are SDK-only. With fetch, you must manually manage conversation history.
---
Thinking Mode
Gemini 2.5 models have thinking mode enabled by default for enhanced quality. You can configure the thinking budget.
Configure Thinking Budget (SDK)
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Solve this complex math problem: ...',
config: {
thinkingConfig: {
thinkingBudget: 8192 // Max tokens for thinking (default: model-dependent)
}
}
});Configure Thinking Budget (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Solve this complex math problem: ...' }] }],
generationConfig: {
thinkingConfig: {
thinkingBudget: 8192
}
}
}),
}
);Key Points:
- Thinking mode is always enabled on Gemini 2.5 models (cannot be disabled)
- Higher thinking budgets allow more internal reasoning (may increase latency)
- Default budget varies by model (usually sufficient for most tasks)
- Only increase budget for very complex reasoning tasks
---
Generation Configuration
Customize model behavior with generation parameters.
All Configuration Options (SDK)
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Write a creative story',
config: {
temperature: 0.9, // Randomness (0.0-2.0, default: 1.0)
topP: 0.95, // Nucleus sampling (0.0-1.0)
topK: 40, // Top-k sampling
maxOutputTokens: 2048, // Max tokens to generate
stopSequences: ['END'], // Stop generation if these appear
responseMimeType: 'text/plain', // Or 'application/json' for JSON mode
candidateCount: 1 // Number of response candidates (usually 1)
}
});All Configuration Options (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Write a creative story' }] }],
generationConfig: {
temperature: 0.9,
topP: 0.95,
topK: 40,
maxOutputTokens: 2048,
stopSequences: ['END'],
responseMimeType: 'text/plain',
candidateCount: 1
}
}),
}
);Parameter Guidelines
| Parameter | Range | Default | Use Case |
|---|---|---|---|
| temperature | 0.0-2.0 | 1.0 | Lower = more focused, higher = more creative |
| topP | 0.0-1.0 | 0.95 | Nucleus sampling threshold |
| topK | 1-100+ | 40 | Limit to top K tokens |
| maxOutputTokens | 1-65536 | Model max | Control response length |
| stopSequences | Array | None | Stop generation at specific strings |
Tips:
- For factual tasks: Use low temperature (0.0-0.3)
- For creative tasks: Use high temperature (0.7-1.5)
- topP and topK both control randomness; use one or the other (not both)
- Always set maxOutputTokens to prevent excessive generation
---
Context Caching
Context caching allows you to cache frequently used content (like system instructions, large documents, or video files) to reduce costs by up to 90% and improve latency.
How It Works
1. Create a cache with your repeated content 2. Reference the cache in subsequent requests 3. Save tokens - cached tokens cost significantly less 4. TTL management - caches expire after specified time
Benefits
- Cost savings: Up to 90% reduction on cached tokens
- Reduced latency: Faster responses by reusing processed content
- Consistent context: Same large context across multiple requests
Cache Creation (SDK)
import { GoogleGenAI } from '@google/genai';
import fs from 'fs';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Create a cache for a large document
const documentText = fs.readFileSync('./large-document.txt', 'utf-8');
const cache = await ai.caches.create({
model: 'gemini-2.5-flash',
config: {
displayName: 'large-doc-cache', // Identifier for the cache
systemInstruction: 'You are an expert at analyzing legal documents.',
contents: documentText,
ttl: '3600s', // Cache for 1 hour
}
});
console.log('Cache created:', cache.name);
console.log('Expires at:', cache.expireTime);Cache Creation (Fetch)
const response = await fetch(
'https://generativelanguage.googleapis.com/v1beta/cachedContents',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
model: 'models/gemini-2.5-flash',
displayName: 'large-doc-cache',
systemInstruction: {
parts: [{ text: 'You are an expert at analyzing legal documents.' }]
},
contents: [
{ parts: [{ text: documentText }] }
],
ttl: '3600s'
}),
}
);
const cache = await response.json();
console.log('Cache created:', cache.name);Using a Cache (SDK)
// Generate content using the cache
const response = await ai.models.generateContent({
model: cache.name, // Use cache name as model
contents: 'Summarize the key points in the document'
});
console.log(response.text);Using a Cache (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/${cache.name}:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{ parts: [{ text: 'Summarize the key points in the document' }] }
]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);Update Cache TTL (SDK)
import { UpdateCachedContentConfig } from '@google/genai';
await ai.caches.update({
name: cache.name,
config: {
ttl: '7200s' // Extend to 2 hours
}
});Update Cache with Expiration Time (SDK)
// Set specific expiration time (must be timezone-aware)
const in10Minutes = new Date(Date.now() + 10 * 60 * 1000);
await ai.caches.update({
name: cache.name,
config: {
expireTime: in10Minutes
}
});List and Delete Caches (SDK)
// List all caches
const caches = await ai.caches.list();
for (const cache of caches) {
console.log(cache.name, cache.displayName);
}
// Delete a specific cache
await ai.caches.delete({ name: cache.name });Caching with Video Files
import { GoogleGenAI } from '@google/genai';
import fs from 'fs';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// Upload video file
const videoFile = await ai.files.upload({
file: fs.createReadStream('./video.mp4')
});
// Wait for processing
while (videoFile.state.name === 'PROCESSING') {
await new Promise(resolve => setTimeout(resolve, 2000));
videoFile = await ai.files.get({ name: videoFile.name });
}
// Create cache with video
const cache = await ai.caches.create({
model: 'gemini-2.5-flash',
config: {
displayName: 'video-analysis-cache',
systemInstruction: 'You are an expert video analyzer.',
contents: [videoFile],
ttl: '300s' // 5 minutes
}
});
// Use cache for multiple queries
const response1 = await ai.models.generateContent({
model: cache.name,
contents: 'What happens in the first minute?'
});
const response2 = await ai.models.generateContent({
model: cache.name,
contents: 'Describe the main characters'
});Key Points
When to Use Caching:
- Large system instructions used repeatedly
- Long documents analyzed multiple times
- Video/audio files queried with different prompts
- Consistent context across conversation sessions
TTL Guidelines:
- Short sessions: 300s (5 min) to 3600s (1 hour)
- Long sessions: 3600s (1 hour) to 86400s (24 hours)
- Maximum: 7 days
Cost Savings:
- Cached input tokens: ~90% cheaper than regular tokens
- Output tokens: Same price (not cached)
Important:
- You must use explicit model version suffixes (e.g.,
gemini-2.5-flash-001, NOT justgemini-2.5-flash) - Caches are automatically deleted after TTL expires
- Update TTL before expiration to extend cache lifetime
---
Code Execution
Gemini models can generate and execute Python code to solve problems requiring computation, data analysis, or visualization.
How It Works
1. Model generates executable Python code 2. Code runs in secure sandbox 3. Results are returned to the model 4. Model incorporates results into response
Supported Operations
- Mathematical calculations
- Data analysis and statistics
- File processing (CSV, JSON, etc.)
- Chart and graph generation
- Algorithm implementation
- Data transformations
Available Python Packages
Standard Library:
math,statistics,random,datetime,json,csv,recollections,itertools,functools
Data Science:
numpy,pandas,scipy
Visualization:
matplotlib,seaborn
Note: Limited package availability compared to full Python environment
Basic Code Execution (SDK)
import { GoogleGenAI, Tool, ToolCodeExecution } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation.',
config: {
tools: [{ codeExecution: {} }]
}
});
// Parse response parts
for (const part of response.candidates[0].content.parts) {
if (part.text) {
console.log('Text:', part.text);
}
if (part.executableCode) {
console.log('Generated Code:', part.executableCode.code);
}
if (part.codeExecutionResult) {
console.log('Execution Output:', part.codeExecutionResult.output);
}
}Basic Code Execution (Fetch)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
tools: [{ code_execution: {} }],
contents: [
{
parts: [
{ text: 'What is the sum of the first 50 prime numbers? Generate and run code.' }
]
}
]
}),
}
);
const data = await response.json();
for (const part of data.candidates[0].content.parts) {
if (part.text) {
console.log('Text:', part.text);
}
if (part.executableCode) {
console.log('Code:', part.executableCode.code);
}
if (part.codeExecutionResult) {
console.log('Result:', part.codeExecutionResult.output);
}
}Chat with Code Execution (SDK)
const chat = await ai.chats.create({
model: 'gemini-2.5-flash',
config: {
tools: [{ codeExecution: {} }]
}
});
let response = await chat.sendMessage('I have a math question for you.');
console.log(response.text);
response = await chat.sendMessage(
'Calculate the Fibonacci sequence up to the 20th number and sum them.'
);
// Model will generate and execute code, then provide answer
for (const part of response.candidates[0].content.parts) {
if (part.text) console.log(part.text);
if (part.executableCode) console.log('Code:', part.executableCode.code);
if (part.codeExecutionResult) console.log('Output:', part.codeExecutionResult.output);
}Data Analysis Example
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: `
Analyze this sales data and calculate:
1. Total revenue
2. Average sale price
3. Best-selling month
Data (CSV format):
month,sales,revenue
Jan,150,45000
Feb,200,62000
Mar,175,53000
Apr,220,68000
`,
config: {
tools: [{ codeExecution: {} }]
}
});
// Model will generate pandas/numpy code to analyze data
for (const part of response.candidates[0].content.parts) {
if (part.text) console.log(part.text);
if (part.executableCode) console.log('Analysis Code:', part.executableCode.code);
if (part.codeExecutionResult) console.log('Results:', part.codeExecutionResult.output);
}Visualization Example
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Create a bar chart showing the distribution of prime numbers under 100 by their last digit. Generate the chart and describe the pattern.',
config: {
tools: [{ codeExecution: {} }]
}
});
// Model generates matplotlib code, executes it, and describes results
for (const part of response.candidates[0].content.parts) {
if (part.text) console.log(part.text);
if (part.executableCode) console.log('Chart Code:', part.executableCode.code);
if (part.codeExecutionResult) {
// Note: Chart image data would be in output
console.log('Execution completed');
}
}Response Structure
{
candidates: [
{
content: {
parts: [
{ text: "I'll calculate that for you." },
{
executableCode: {
language: "PYTHON",
code: "def is_prime(n):\n if n <= 1:\n return False\n ..."
}
},
{
codeExecutionResult: {
outcome: "OUTCOME_OK", // or "OUTCOME_FAILED"
output: "5117\n"
}
},
{ text: "The sum of the first 50 prime numbers is 5117." }
]
}
}
]
}Error Handling
for (const part of response.candidates[0].content.parts) {
if (part.codeExecutionResult) {
if (part.codeExecutionResult.outcome === 'OUTCOME_FAILED') {
console.error('Code execution failed:', part.codeExecutionResult.output);
} else {
console.log('Success:', part.codeExecutionResult.output);
}
}
}Key Points
When to Use Code Execution:
- Complex mathematical calculations
- Data analysis and statistics
- Algorithm implementations
- File parsing and processing
- Chart generation
- Computational problems
Limitations:
- Sandbox environment (limited file system access)
- Limited Python package availability
- Execution timeout limits
- No network access from code
- No persistent state between executions
Best Practices:
- Specify what calculation or analysis you need clearly
- Request code generation explicitly ("Generate and run code...")
- Check
outcomefield for errors - Use for deterministic computations, not for general programming
Important:
- Available on all Gemini 2.5 models (Pro, Flash, Flash-Lite)
- Code runs in isolated sandbox for security
- Supports Python with standard library and common data science packages
---
Grounding with Google Search
Grounding connects the model to real-time web information, reducing hallucinations and providing up-to-date, fact-checked responses with citations.
How It Works
1. Model determines if it needs current information 2. Automatically performs Google Search 3. Processes search results 4. Incorporates findings into response 5. Provides citations and source URLs
Benefits
- Real-time information: Access to current events and data
- Reduced hallucinations: Answers grounded in web sources
- Verifiable: Citations allow fact-checking
- Up-to-date: Not limited to model's training cutoff
Two Grounding APIs
1. Google Search (googleSearch) - Recommended for Gemini 2.5
const groundingTool = {
googleSearch: {}
};Features:
- Simple configuration
- Automatic search when needed
- Available on all Gemini 2.5 models
2. Google Search Retrieval (googleSearchRetrieval) - Legacy (Gemini 1.5)
const retrievalTool = {
googleSearchRetrieval: {
dynamicRetrievalConfig: {
mode: 'MODE_DYNAMIC',
dynamicThreshold: 0.7 // Only search if confidence < 70%
}
}
};Features:
- Dynamic threshold control
- Used with Gemini 1.5 models
- More configuration options
Basic Grounding (SDK) - Gemini 2.5
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Who won the euro 2024?',
config: {
tools: [{ googleSearch: {} }]
}
});
console.log(response.text);
// Check if grounding was used
if (response.candidates[0].groundingMetadata) {
console.log('Search was performed!');
console.log('Sources:', response.candidates[0].groundingMetadata);
}Basic Grounding (Fetch) - Gemini 2.5
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [
{ parts: [{ text: 'Who won the euro 2024?' }] }
],
tools: [
{ google_search: {} }
]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);
if (data.candidates[0].groundingMetadata) {
console.log('Grounding metadata:', data.candidates[0].groundingMetadata);
}Dynamic Retrieval (SDK) - Gemini 1.5
import { GoogleGenAI, DynamicRetrievalConfigMode } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-1.5-flash',
contents: 'Who won the euro 2024?',
config: {
tools: [
{
googleSearchRetrieval: {
dynamicRetrievalConfig: {
mode: DynamicRetrievalConfigMode.MODE_DYNAMIC,
dynamicThreshold: 0.7 // Search only if confidence < 70%
}
}
}
]
}
});
console.log(response.text);
if (!response.candidates[0].groundingMetadata) {
console.log('Model answered from its own knowledge (high confidence)');
}Grounding Metadata Structure
{
groundingMetadata: {
searchQueries: [
{ text: "euro 2024 winner" }
],
webPages: [
{
url: "https://example.com/euro-2024-results",
title: "UEFA Euro 2024 Final Results",
snippet: "Spain won UEFA Euro 2024..."
}
],
citations: [
{
startIndex: 42,
endIndex: 47,
uri: "https://example.com/euro-2024-results"
}
],
retrievalQueries: [
{
query: "who won euro 2024 final"
}
]
}
}Chat with Grounding (SDK)
const chat = await ai.chats.create({
model: 'gemini-2.5-flash',
config: {
tools: [{ googleSearch: {} }]
}
});
let response = await chat.sendMessage('What are the latest developments in quantum computing?');
console.log(response.text);
// Check grounding sources
if (response.candidates[0].groundingMetadata) {
const sources = response.candidates[0].groundingMetadata.webPages || [];
console.log(`Sources used: ${sources.length}`);
sources.forEach(source => {
console.log(`- ${source.title}: ${source.url}`);
});
}
// Follow-up still has grounding enabled
response = await chat.sendMessage('Which company made the biggest breakthrough?');
console.log(response.text);Combining Grounding with Function Calling
const weatherFunction = {
name: 'get_current_weather',
description: 'Get current weather for a location',
parametersJsonSchema: {
type: 'object',
properties: {
location: { type: 'string', description: 'City name' }
},
required: ['location']
}
};
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What is the weather like in the city that won Euro 2024?',
config: {
tools: [
{ googleSearch: {} },
{ functionDeclarations: [weatherFunction] }
]
}
});
// Model will:
// 1. Use Google Search to find Euro 2024 winner
// 2. Call get_current_weather function with the city
// 3. Combine both results in responseChecking if Grounding was Used
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'What is 2+2?', // Model knows this without search
config: {
tools: [{ googleSearch: {} }]
}
});
if (!response.candidates[0].groundingMetadata) {
console.log('Model answered from its own knowledge (no search needed)');
} else {
console.log('Search was performed');
}Key Points
When to Use Grounding:
- Current events and news
- Real-time data (stock prices, sports scores, weather)
- Fact-checking and verification
- Questions about recent developments
- Information beyond model's training cutoff
When NOT to Use:
- General knowledge questions
- Mathematical calculations
- Code generation
- Creative writing
- Tasks requiring internal reasoning only
Cost Considerations:
- Grounding adds latency (search takes time)
- Additional token costs for retrieved content
- Use
dynamicThresholdto control when searches happen (Gemini 1.5)
Important Notes:
- Grounding requires Google Cloud project (not just API key)
- Search results quality depends on query phrasing
- Citations may not cover all facts in response
- Search is performed automatically based on confidence
Gemini 2.5 vs 1.5:
- Gemini 2.5: Use
googleSearch(simple, recommended) - Gemini 1.5: Use
googleSearchRetrievalwithdynamicThreshold
Best Practices:
- Always check
groundingMetadatato see if search was used - Display citations to users for transparency
- Use specific, well-phrased questions for better search results
- Combine with function calling for hybrid workflows
---
Error Handling
Common Errors
1. Invalid API Key (401)
{
error: {
code: 401,
message: 'API key not valid. Please pass a valid API key.',
status: 'UNAUTHENTICATED'
}
}Solution: Verify GEMINI_API_KEY environment variable is set correctly.
2. Rate Limit Exceeded (429)
{
error: {
code: 429,
message: 'Resource has been exhausted (e.g. check quota).',
status: 'RESOURCE_EXHAUSTED'
}
}Solution: Implement exponential backoff retry strategy.
3. Model Not Found (404)
{
error: {
code: 404,
message: 'models/gemini-3.0-flash is not found',
status: 'NOT_FOUND'
}
}Solution: Use correct model names: gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite
4. Context Length Exceeded (400)
{
error: {
code: 400,
message: 'Request payload size exceeds the limit',
status: 'INVALID_ARGUMENT'
}
}Solution: Reduce input size. Gemini 2.5 models support 1,048,576 input tokens max.
Exponential Backoff Pattern
async function generateWithRetry(request, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await ai.models.generateContent(request);
} catch (error) {
if (error.status === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
}---
Rate Limits
Free Tier (Gemini API)
Rate limits vary by model:
Gemini 2.5 Pro:
- Requests per minute: 5 RPM
- Tokens per minute: 125,000 TPM
- Requests per day: 100 RPD
Gemini 2.5 Flash:
- Requests per minute: 10 RPM
- Tokens per minute: 250,000 TPM
- Requests per day: 250 RPD
Gemini 2.5 Flash-Lite:
- Requests per minute: 15 RPM
- Tokens per minute: 250,000 TPM
- Requests per day: 1,000 RPD
Paid Tier (Tier 1)
Requires billing account linked to your Google Cloud project.
Gemini 2.5 Pro:
- Requests per minute: 150 RPM
- Tokens per minute: 2,000,000 TPM
- Requests per day: 10,000 RPD
Gemini 2.5 Flash:
- Requests per minute: 1,000 RPM
- Tokens per minute: 1,000,000 TPM
- Requests per day: 10,000 RPD
Gemini 2.5 Flash-Lite:
- Requests per minute: 4,000 RPM
- Tokens per minute: 4,000,000 TPM
- Requests per day: Not specified
Higher Tiers (Tier 2 & 3)
Tier 2 (requires $250+ spending and 30-day wait):
- Even higher limits available
Tier 3 (requires $1,000+ spending and 30-day wait):
- Maximum limits available
Tips:
- Implement rate limit handling with exponential backoff
- Use batch processing for high-volume tasks
- Monitor usage in Google AI Studio
- Choose the right model based on your rate limit needs
- Official rate limits: https://ai.google.dev/gemini-api/docs/rate-limits
---
SDK Migration Guide
From @google/generative-ai to @google/genai
1. Update Package
# Remove deprecated SDK
npm uninstall @google/generative-ai
# Install current SDK
npm install @google/genai@1.27.02. Update Imports
Old (DEPRECATED):
import { GoogleGenerativeAI } from '@google/generative-ai';
const genAI = new GoogleGenerativeAI(apiKey);
const model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });New (CURRENT):
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey });
// Use ai.models.generateContent() directly3. Update API Calls
Old:
const result = await model.generateContent(prompt);
const response = await result.response;
const text = response.text();New:
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: prompt
});
const text = response.text;4. Update Streaming
Old:
const result = await model.generateContentStream(prompt);
for await (const chunk of result.stream) {
console.log(chunk.text());
}New:
const response = await ai.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: prompt
});
for await (const chunk of response) {
console.log(chunk.text);
}5. Update Chat
Old:
const chat = model.startChat();
const result = await chat.sendMessage(message);
const response = await result.response;New:
const chat = await ai.models.createChat({ model: 'gemini-2.5-flash' });
const response = await chat.sendMessage(message);
// response.text is directly available---
Production Best Practices
1. Always Do
✅ Use @google/genai (NOT @google/generative-ai) ✅ Set maxOutputTokens to prevent excessive generation ✅ Implement rate limit handling with exponential backoff ✅ Use environment variables for API keys (never hardcode) ✅ Validate inputs before sending to API (save costs) ✅ Use streaming for better UX on long responses ✅ Choose the right model based on your needs (Pro for complex reasoning, Flash for balance, Flash-Lite for speed) ✅ Handle errors gracefully with try-catch ✅ Monitor token usage for cost control ✅ Use correct model names: gemini-2.5-pro/flash/flash-lite
2. Never Do
❌ Never use @google/generative-ai (deprecated!) ❌ Never hardcode API keys in code ❌ Never claim 2M context for Gemini 2.5 (it's 1,048,576 input tokens) ❌ Never expose API keys in client-side code ❌ Never skip error handling (always try-catch) ❌ Never use generic rate limits (each model has different limits - check official docs) ❌ Never send PII without user consent ❌ Never trust user input without validation ❌ Never ignore rate limits (will get 429 errors) ❌ Never use old model names like gemini-1.5-pro (use 2.5 models)
3. Security
- API Key Storage: Use environment variables or secret managers
- Server-Side Only: Never expose API keys in browser JavaScript
- Input Validation: Sanitize all user inputs before API calls
- Rate Limiting: Implement your own rate limits to prevent abuse
- Error Messages: Don't expose API keys or sensitive data in error logs
4. Cost Optimization
- Choose Right Model: Use Flash for most tasks, Pro only when needed
- Set Token Limits: Use maxOutputTokens to control costs
- Batch Requests: Process multiple items efficiently
- Cache Results: Store responses when appropriate
- Monitor Usage: Track token consumption in Google Cloud Console
5. Performance
- Use Streaming: Better perceived latency for long responses
- Parallel Requests: Use Promise.all() for independent calls
- Edge Deployment: Deploy to Cloudflare Workers for low latency
- Connection Pooling: Reuse HTTP connections when possible
---
Quick Reference
Installation
npm install @google/genai@1.27.0Environment
export GEMINI_API_KEY="..."Models (2025)
gemini-2.5-pro(1,048,576 in / 65,536 out) - Best for complex reasoninggemini-2.5-flash(1,048,576 in / 65,536 out) - Best price-performance balancegemini-2.5-flash-lite(1,048,576 in / 65,536 out) - Fastest, most cost-effective
Basic Generation
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Your prompt here'
});
console.log(response.text);Streaming
const response = await ai.models.generateContentStream({...});
for await (const chunk of response) {
console.log(chunk.text);
}Multimodal
contents: [
{
parts: [
{ text: 'What is this?' },
{ inlineData: { data: base64Image, mimeType: 'image/jpeg' } }
]
}
]Function Calling
config: {
tools: [{ functionDeclarations: [...] }]
}---
Last Updated: 2025-10-25 Production Validated: All features tested with @google/genai@1.27.0 Phase: 2 Complete ✅ (All Core + Advanced Features)
google-gemini-api
Google Gemini API Skill for Claude Code CLI
Status: Phase 2 Complete ✅ Latest SDK: @google/genai@1.27.0 (⚠️ NOT @google/generative-ai which is DEPRECATED) API Coverage: Text Generation, Multimodal, Function Calling, Streaming, Thinking Mode, Context Caching, Code Execution, Grounding with Google Search
---
⚠️ CRITICAL: SDK Migration Warning
DEPRECATED: @google/generative-ai (sunset Nov 30, 2025) CURRENT: @google/genai v1.27+ (use this!)
If you see code using @google/generative-ai, it's outdated! This skill uses the correct current SDK.
---
What This Skill Does
This skill provides comprehensive knowledge for building applications with Google Gemini API using the correct current SDK (@google/genai v1.27+) and accurate 2025 model information.
Key Capabilities
Phase 1 - Core Features
✅ Text Generation with Gemini 2.5 Pro/Flash/Flash-Lite (GA models) ✅ Streaming with Server-Sent Events (SSE) and async iteration ✅ Multimodal inputs (text + images + video + audio + PDFs) ✅ Function calling (basic + parallel execution) ✅ Thinking mode (adaptive reasoning on 2.5 models) ✅ System instructions for behavior guidance ✅ Multi-turn chat (conversation history management) ✅ Both Node.js SDK (@google/genai) and fetch-based (Cloudflare Workers) approaches ✅ Accurate context windows: 1,048,576 input / 65,536 output tokens (NOT 2M for 2.5 models!)
Phase 2 - Advanced Features
✅ Context Caching (cost optimization with TTL-based caching - up to 90% savings) ✅ Code Execution (built-in Python sandbox for data analysis and computation) ✅ Grounding with Google Search (real-time web information + citations)
---
Auto-Trigger Keywords
Primary Keywords (Core API)
gemini apigoogle gemini@google/genaigemini-2.5-progemini-2.5-flashgemini-2.5-flash-litegenai sdkgoogle aigemini sdk
Model Names
gemini 2.5gemini 2.0gemini progemini flashgemini flash lite
Text Generation
gemini text generationgenerate content geminigemini chatgemini completiongemini response
Streaming
gemini streamingstream geminigemini sseserver-sent events geminiasync iteration geministreaming tokens gemini
Multimodal Keywords
gemini multimodalgemini visiongemini imagegemini videogemini audiogemini pdfimage understanding geminianalyze image geminivideo understanding geminiaudio transcription geminipdf parsing gemini
Function Calling
function calling geminigemini toolstool calling geminifunction declarations geminiparallel function calling geminicompositional function callinggemini tool use
Thinking Mode
thinking mode geminigemini thinkingadaptive reasoning geminithinking budget geminigemini reasoning
System Instructions & Chat
system instructions geminigemini system promptmulti-turn geminiconversation history geminichat history geminigemini chat sdk
Configuration
gemini temperaturegemini top-pgemini top-kstop sequences geminigeneration config geminiresponse mime type gemini
Context Caching (Phase 2)
context caching geminigemini cachinggemini cache ttlprompt caching geminicache tokens geminigemini cost optimizationreduce cost geminigemini cache videocache documents gemini90% savings gemini
Code Execution (Phase 2)
code execution geminigemini pythongemini code interpreterrun code geminiexecutable code geminigemini data analysisgemini calculationsgemini pandasgemini numpygemini matplotlibgenerate and run code
Grounding with Google Search (Phase 2)
grounding geminigoogle search geminigemini groundingreal-time information geminigemini search retrievalgemini citationsfact-checking geminigemini sourcesweb search geminicurrent events gemini
SDK Migration
@google/generative-ai deprecatedmigrate gemini sdkgemini sdk migrationgenerative-ai deprecatedupdate gemini sdk
Context Window
gemini context windowgemini token limitgemini 1m tokensgemini 2m tokens(⚠️ only Gemini 1.5 Pro has 2M, NOT 2.5 models!)context length gemini
Error Keywords
gemini api errorgemini 401gemini 429gemini rate limitinvalid api key geminimodel not found geminigemini context window exceededfunction calling error geminitool schema invalid geministreaming parse error geminimultimodal format error geminithinking mode not supporteddeprecated sdk error@google/generative-ai not found
Error Keywords - Phase 2
cache not found geminicache ttl expiredinvalid model version geminicode execution failed geminiexecution timeout geminipython package not available geminigrounding requires google cloudgrounding not working geminino grounding metadata
Integration Keywords
nextjs geminireact geminicloudflare workers geminivercel geminigemini backendgemini servergemini edge runtime
Comparison Keywords
gemini vs openaigemini vs claudegemini vs gptgoogle ai vs openai
---
When to Use This Skill
✅ Use google-gemini-api When:
- Building AI applications with Google's Gemini models
- Need multimodal AI (text + images + video + audio + PDFs)
- Implementing long-context applications (1M+ tokens)
- Using thinking mode for complex reasoning
- Need function calling with parallel execution
- Want streaming responses for better UX
- Deploying to Cloudflare Workers or other edge runtimes
- Building chat applications with conversation history
- Need to migrate from deprecated @google/generative-ai
❌ Don't Use google-gemini-api When:
- You specifically need embeddings (see separate
google-gemini-embeddingsskill for text-embedding-004) - You're using a different AI API provider (OpenAI, Anthropic Claude, etc.)
---
Quick Example
Text Generation (Node.js SDK)
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Explain quantum computing in simple terms'
});
console.log(response.text);Text Generation (Fetch - Cloudflare Workers)
const response = await fetch(
`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-goog-api-key': env.GEMINI_API_KEY,
},
body: JSON.stringify({
contents: [{ parts: [{ text: 'Explain quantum computing in simple terms' }] }]
}),
}
);
const data = await response.json();
console.log(data.candidates[0].content.parts[0].text);Streaming
const response = await ai.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: 'Write a 200-word story about AI'
});
for await (const chunk of response) {
process.stdout.write(chunk.text);
}---
Known Issues Prevented
| Issue | Cause | Solution in Skill |
|---|---|---|
| Using deprecated SDK | Installing @google/generative-ai | Prominent warnings + migration guide |
| Wrong context window claims | Claiming 2M tokens for 2.5 models | Accurate: 1,048,576 input tokens |
| Model not found errors | Using old/wrong model names | Current model list (gemini-2.5-pro/flash/flash-lite) |
| Chat not working with fetch | Chat is SDK-only feature | Document SDK requirement for chat helpers |
| Function calling on Flash-Lite | Model doesn't support it | Model capabilities matrix |
| Invalid API key (401) | Missing GEMINI_API_KEY | Environment setup guide |
| Rate limit errors (429) | Too many requests | Exponential backoff pattern |
| Streaming parse errors | Incorrect SSE parsing | Complete SSE implementation |
| Multimodal format errors | Wrong image/video encoding | Base64/URL examples |
| Function schema errors | Invalid OpenAPI subset | Schema validation examples |
| Thinking mode on old models | Only 2.5 models support it | Model feature matrix |
| Parameter conflicts | Using unsupported params | Generation config reference |
| Token counting errors | Multimodal token estimation | Token counting guide |
| System instruction placement | Wrong position in request | Correct structure examples |
| Parallel function call errors | Dependencies not handled | Compositional vs parallel guide |
---
Current Models (2025)
Gemini 2.5 Series (General Availability)
- gemini-2.5-pro: State-of-the-art thinking model (1,048,576 input / 65,536 output tokens)
- gemini-2.5-flash: Best price-performance (1,048,576 input / 65,536 output tokens)
- gemini-2.5-flash-lite: Cost-optimized, fastest (1,048,576 input / 65,536 output tokens)
Feature Matrix
| Feature | Pro | Flash | Flash-Lite |
|---|---|---|---|
| Thinking Mode | ✅ | ✅ | ✅ |
| Function Calling | ✅ | ✅ | ❌ |
| Multimodal | ✅ | ✅ | ✅ |
| Streaming | ✅ | ✅ | ✅ |
| System Instructions | ✅ | ✅ | ✅ |
⚠️ Note: Gemini 2.5 Flash-Lite does NOT support function calling!
---
Token Efficiency
Without Skill
- Research APIs + SDK: ~22,000 tokens
- Fall into deprecated SDK trap: +5,000 tokens (debugging)
- Context window confusion: +3,000 tokens (debugging)
- Total: ~30,000 tokens
With Skill
- Skill discovery + implementation: ~10,500 tokens
- Zero debugging (all errors prevented)
- Total: ~10,500 tokens
Savings: ~65% (19,500 tokens)
---
What You Get
SKILL.md Content
- Complete API reference (1200+ lines)
- Gemini 2.5 specific guidance
- Streaming patterns (SDK + fetch)
- Function calling (basic + parallel)
- Multimodal examples (images, video, audio, PDFs)
- Thinking mode configuration
- System instructions & chat
- SDK migration guide
- Top 15 errors with solutions
- Production best practices
11 Templates
1. package.json (dependencies) 2. text-generation-basic.ts (SDK) 3. text-generation-fetch.ts (Cloudflare Workers) 4. streaming-chat.ts (SDK with async iteration) 5. streaming-fetch.ts (SSE parsing) 6. multimodal-image.ts (vision) 7. multimodal-video-audio.ts (video/audio understanding) 8. function-calling-basic.ts (tool use) 9. function-calling-parallel.ts (parallel execution) 10. thinking-mode.ts (configure thinking budget) 11. cloudflare-worker.ts (complete Worker example)
8 Reference Docs
1. models-guide.md (2.5 Pro/Flash/Flash-Lite comparison with ACCURATE context windows) 2. sdk-migration-guide.md (complete migration from deprecated SDK) 3. function-calling-patterns.md (tool use best practices) 4. multimodal-guide.md (images, video, audio, PDFs) 5. thinking-mode-guide.md (when to use, budget configuration) 6. generation-config.md (all parameters explained) 7. streaming-patterns.md (SSE implementation for SDK + fetch) 8. top-errors.md (15+ documented errors with solutions)
1 Script
- check-versions.sh (verify @google/genai version, warn if using deprecated SDK)
---
Installation
# From claude-skills repo root
./scripts/install-skill.sh google-gemini-api
# Verify installation
ls -la ~/.claude/skills/google-gemini-api---
Quick Reference
Package Version
npm install @google/genai@1.27.0⚠️ NOT:
npm install @google/generative-ai # DEPRECATED!Environment Variables
export GEMINI_API_KEY="..."Models Overview (2025)
- Gemini 2.5 Pro:
gemini-2.5-pro(thinking, function calling, multimodal) - Gemini 2.5 Flash:
gemini-2.5-flash(best price-performance) - Gemini 2.5 Flash-Lite:
gemini-2.5-flash-lite(fastest, no function calling)
Context Windows (ACCURATE)
- Gemini 2.5 models: 1,048,576 input / 65,536 output tokens
- NOT 2M tokens (only Gemini 1.5 Pro has 2M, which is an older model)
---
Official Documentation
- Gemini API Overview: https://ai.google.dev/gemini-api/docs
- @google/genai SDK: https://github.com/googleapis/js-genai
- Models Guide: https://ai.google.dev/gemini-api/docs/models
- Text Generation: https://ai.google.dev/gemini-api/docs/text-generation
- Function Calling: https://ai.google.dev/gemini-api/docs/function-calling
- Multimodal: https://ai.google.dev/gemini-api/docs/vision
- Streaming: https://ai.google.dev/gemini-api/docs/streaming
- Migration Guide: https://ai.google.dev/gemini-api/docs/migrate-to-genai
---
Production Validated: Templates tested with @google/genai@1.27.0 Last Updated: 2025-10-25 Maintainer: Jeremy Dawes | Jezweb
{
"description": "|",
"metadata": {
"license": "MIT"
},
"references": {
"files": [
"references/code-execution-patterns.md",
"references/context-caching-guide.md",
"references/function-calling-patterns.md",
"references/generation-config.md",
"references/grounding-guide.md",
"references/models-guide.md",
"references/multimodal-guide.md",
"references/sdk-migration-guide.md",
"references/streaming-patterns.md",
"references/thinking-mode-guide.md",
"references/top-errors.md"
]
},
"content": "**Version**: Phase 2 Complete ✅\r\n**Package**: @google/genai@1.27.0 (⚠️ NOT @google/generative-ai)\r\n**Last Updated**: 2025-10-25\r\n\r\n---\r\n\r\n\r\n### From @google/generative-ai to @google/genai\r\n\r\n#### 1. Update Package\r\n\r\n```bash\r\nnpm uninstall @google/generative-ai",
"name": "google-gemini-api",
"id": "google-gemini-api",
"sections": {
"Table of Contents": "**Phase 1 - Core Features**:\r\n1. [Quick Start](#quick-start)\r\n2. [Current Models (2025)](#current-models-2025)\r\n3. [SDK vs Fetch Approaches](#sdk-vs-fetch-approaches)\r\n4. [Text Generation](#text-generation)\r\n5. [Streaming](#streaming)\r\n6. [Multimodal Inputs](#multimodal-inputs)\r\n7. [Function Calling](#function-calling)\r\n8. [System Instructions](#system-instructions)\r\n9. [Multi-turn Chat](#multi-turn-chat)\r\n10. [Thinking Mode](#thinking-mode)\r\n11. [Generation Configuration](#generation-configuration)\r\n\r\n**Phase 2 - Advanced Features**:\r\n12. [Context Caching](#context-caching)\r\n13. [Code Execution](#code-execution)\r\n14. [Grounding with Google Search](#grounding-with-google-search)\r\n\r\n**Common Reference**:\r\n15. [Error Handling](#error-handling)\r\n16. [Rate Limits](#rate-limits)\r\n17. [SDK Migration Guide](#sdk-migration-guide)\r\n18. [Production Best Practices](#production-best-practices)\r\n\r\n---",
"SDK Migration Guide": "npm install @google/genai@1.27.0\r\n```\r\n\r\n#### 2. Update Imports\r\n\r\n**Old (DEPRECATED):**\r\n```typescript\r\nimport { GoogleGenerativeAI } from '@google/generative-ai';\r\nconst genAI = new GoogleGenerativeAI(apiKey);\r\nconst model = genAI.getGenerativeModel({ model: 'gemini-2.5-flash' });\r\n```\r\n\r\n**New (CURRENT):**\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\nconst ai = new GoogleGenAI({ apiKey });\r\n// Use ai.models.generateContent() directly\r\n```\r\n\r\n#### 3. Update API Calls\r\n\r\n**Old:**\r\n```typescript\r\nconst result = await model.generateContent(prompt);\r\nconst response = await result.response;\r\nconst text = response.text();\r\n```\r\n\r\n**New:**\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: prompt\r\n});\r\nconst text = response.text;\r\n```\r\n\r\n#### 4. Update Streaming\r\n\r\n**Old:**\r\n```typescript\r\nconst result = await model.generateContentStream(prompt);\r\nfor await (const chunk of result.stream) {\r\n console.log(chunk.text());\r\n}\r\n```\r\n\r\n**New:**\r\n```typescript\r\nconst response = await ai.models.generateContentStream({\r\n model: 'gemini-2.5-flash',\r\n contents: prompt\r\n});\r\nfor await (const chunk of response) {\r\n console.log(chunk.text);\r\n}\r\n```\r\n\r\n#### 5. Update Chat\r\n\r\n**Old:**\r\n```typescript\r\nconst chat = model.startChat();\r\nconst result = await chat.sendMessage(message);\r\nconst response = await result.response;\r\n```\r\n\r\n**New:**\r\n```typescript\r\nconst chat = await ai.models.createChat({ model: 'gemini-2.5-flash' });\r\nconst response = await chat.sendMessage(message);\r\n// response.text is directly available\r\n```\r\n\r\n---",
"Rate Limits": "### Free Tier (Gemini API)\r\n\r\nRate limits vary by model:\r\n\r\n**Gemini 2.5 Pro**:\r\n- Requests per minute: 5 RPM\r\n- Tokens per minute: 125,000 TPM\r\n- Requests per day: 100 RPD\r\n\r\n**Gemini 2.5 Flash**:\r\n- Requests per minute: 10 RPM\r\n- Tokens per minute: 250,000 TPM\r\n- Requests per day: 250 RPD\r\n\r\n**Gemini 2.5 Flash-Lite**:\r\n- Requests per minute: 15 RPM\r\n- Tokens per minute: 250,000 TPM\r\n- Requests per day: 1,000 RPD\r\n\r\n### Paid Tier (Tier 1)\r\n\r\nRequires billing account linked to your Google Cloud project.\r\n\r\n**Gemini 2.5 Pro**:\r\n- Requests per minute: 150 RPM\r\n- Tokens per minute: 2,000,000 TPM\r\n- Requests per day: 10,000 RPD\r\n\r\n**Gemini 2.5 Flash**:\r\n- Requests per minute: 1,000 RPM\r\n- Tokens per minute: 1,000,000 TPM\r\n- Requests per day: 10,000 RPD\r\n\r\n**Gemini 2.5 Flash-Lite**:\r\n- Requests per minute: 4,000 RPM\r\n- Tokens per minute: 4,000,000 TPM\r\n- Requests per day: Not specified\r\n\r\n### Higher Tiers (Tier 2 & 3)\r\n\r\n**Tier 2** (requires $250+ spending and 30-day wait):\r\n- Even higher limits available\r\n\r\n**Tier 3** (requires $1,000+ spending and 30-day wait):\r\n- Maximum limits available\r\n\r\n**Tips:**\r\n- Implement rate limit handling with exponential backoff\r\n- Use batch processing for high-volume tasks\r\n- Monitor usage in Google AI Studio\r\n- Choose the right model based on your rate limit needs\r\n- Official rate limits: https://ai.google.dev/gemini-api/docs/rate-limits\r\n\r\n---",
"Grounding with Google Search": "Grounding connects the model to real-time web information, reducing hallucinations and providing up-to-date, fact-checked responses with citations.\r\n\r\n### How It Works\r\n\r\n1. Model determines if it needs current information\r\n2. Automatically performs Google Search\r\n3. Processes search results\r\n4. Incorporates findings into response\r\n5. Provides citations and source URLs\r\n\r\n### Benefits\r\n\r\n- **Real-time information**: Access to current events and data\r\n- **Reduced hallucinations**: Answers grounded in web sources\r\n- **Verifiable**: Citations allow fact-checking\r\n- **Up-to-date**: Not limited to model's training cutoff\r\n\r\n### Two Grounding APIs\r\n\r\n#### 1. Google Search (`googleSearch`) - Recommended for Gemini 2.5\r\n\r\n```typescript\r\nconst groundingTool = {\r\n googleSearch: {}\r\n};\r\n```\r\n\r\n**Features:**\r\n- Simple configuration\r\n- Automatic search when needed\r\n- Available on all Gemini 2.5 models\r\n\r\n#### 2. Google Search Retrieval (`googleSearchRetrieval`) - Legacy (Gemini 1.5)\r\n\r\n```typescript\r\nconst retrievalTool = {\r\n googleSearchRetrieval: {\r\n dynamicRetrievalConfig: {\r\n mode: 'MODE_DYNAMIC',\r\n dynamicThreshold: 0.7 // Only search if confidence < 70%\r\n }\r\n }\r\n};\r\n```\r\n\r\n**Features:**\r\n- Dynamic threshold control\r\n- Used with Gemini 1.5 models\r\n- More configuration options\r\n\r\n### Basic Grounding (SDK) - Gemini 2.5\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Who won the euro 2024?',\r\n config: {\r\n tools: [{ googleSearch: {} }]\r\n }\r\n});\r\n\r\nconsole.log(response.text);\r\n\r\n// Check if grounding was used\r\nif (response.candidates[0].groundingMetadata) {\r\n console.log('Search was performed!');\r\n console.log('Sources:', response.candidates[0].groundingMetadata);\r\n}\r\n```\r\n\r\n### Basic Grounding (Fetch) - Gemini 2.5\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n { parts: [{ text: 'Who won the euro 2024?' }] }\r\n ],\r\n tools: [\r\n { google_search: {} }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconsole.log(data.candidates[0].content.parts[0].text);\r\n\r\nif (data.candidates[0].groundingMetadata) {\r\n console.log('Grounding metadata:', data.candidates[0].groundingMetadata);\r\n}\r\n```\r\n\r\n### Dynamic Retrieval (SDK) - Gemini 1.5\r\n\r\n```typescript\r\nimport { GoogleGenAI, DynamicRetrievalConfigMode } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-1.5-flash',\r\n contents: 'Who won the euro 2024?',\r\n config: {\r\n tools: [\r\n {\r\n googleSearchRetrieval: {\r\n dynamicRetrievalConfig: {\r\n mode: DynamicRetrievalConfigMode.MODE_DYNAMIC,\r\n dynamicThreshold: 0.7 // Search only if confidence < 70%\r\n }\r\n }\r\n }\r\n ]\r\n }\r\n});\r\n\r\nconsole.log(response.text);\r\n\r\nif (!response.candidates[0].groundingMetadata) {\r\n console.log('Model answered from its own knowledge (high confidence)');\r\n}\r\n```\r\n\r\n### Grounding Metadata Structure\r\n\r\n```typescript\r\n{\r\n groundingMetadata: {\r\n searchQueries: [\r\n { text: \"euro 2024 winner\" }\r\n ],\r\n webPages: [\r\n {\r\n url: \"https://example.com/euro-2024-results\",\r\n title: \"UEFA Euro 2024 Final Results\",\r\n snippet: \"Spain won UEFA Euro 2024...\"\r\n }\r\n ],\r\n citations: [\r\n {\r\n startIndex: 42,\r\n endIndex: 47,\r\n uri: \"https://example.com/euro-2024-results\"\r\n }\r\n ],\r\n retrievalQueries: [\r\n {\r\n query: \"who won euro 2024 final\"\r\n }\r\n ]\r\n }\r\n}\r\n```\r\n\r\n### Chat with Grounding (SDK)\r\n\r\n```typescript\r\nconst chat = await ai.chats.create({\r\n model: 'gemini-2.5-flash',\r\n config: {\r\n tools: [{ googleSearch: {} }]\r\n }\r\n});\r\n\r\nlet response = await chat.sendMessage('What are the latest developments in quantum computing?');\r\nconsole.log(response.text);\r\n\r\n// Check grounding sources\r\nif (response.candidates[0].groundingMetadata) {\r\n const sources = response.candidates[0].groundingMetadata.webPages || [];\r\n console.log(`Sources used: ${sources.length}`);\r\n sources.forEach(source => {\r\n console.log(`- ${source.title}: ${source.url}`);\r\n });\r\n}\r\n\r\n// Follow-up still has grounding enabled\r\nresponse = await chat.sendMessage('Which company made the biggest breakthrough?');\r\nconsole.log(response.text);\r\n```\r\n\r\n### Combining Grounding with Function Calling\r\n\r\n```typescript\r\nconst weatherFunction = {\r\n name: 'get_current_weather',\r\n description: 'Get current weather for a location',\r\n parametersJsonSchema: {\r\n type: 'object',\r\n properties: {\r\n location: { type: 'string', description: 'City name' }\r\n },\r\n required: ['location']\r\n }\r\n};\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What is the weather like in the city that won Euro 2024?',\r\n config: {\r\n tools: [\r\n { googleSearch: {} },\r\n { functionDeclarations: [weatherFunction] }\r\n ]\r\n }\r\n});\r\n\r\n// Model will:\r\n// 1. Use Google Search to find Euro 2024 winner\r\n// 2. Call get_current_weather function with the city\r\n// 3. Combine both results in response\r\n```\r\n\r\n### Checking if Grounding was Used\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What is 2+2?', // Model knows this without search\r\n config: {\r\n tools: [{ googleSearch: {} }]\r\n }\r\n});\r\n\r\nif (!response.candidates[0].groundingMetadata) {\r\n console.log('Model answered from its own knowledge (no search needed)');\r\n} else {\r\n console.log('Search was performed');\r\n}\r\n```\r\n\r\n### Key Points\r\n\r\n**When to Use Grounding:**\r\n- Current events and news\r\n- Real-time data (stock prices, sports scores, weather)\r\n- Fact-checking and verification\r\n- Questions about recent developments\r\n- Information beyond model's training cutoff\r\n\r\n**When NOT to Use:**\r\n- General knowledge questions\r\n- Mathematical calculations\r\n- Code generation\r\n- Creative writing\r\n- Tasks requiring internal reasoning only\r\n\r\n**Cost Considerations:**\r\n- Grounding adds latency (search takes time)\r\n- Additional token costs for retrieved content\r\n- Use `dynamicThreshold` to control when searches happen (Gemini 1.5)\r\n\r\n**Important Notes:**\r\n- Grounding requires **Google Cloud project** (not just API key)\r\n- Search results quality depends on query phrasing\r\n- Citations may not cover all facts in response\r\n- Search is performed automatically based on confidence\r\n\r\n**Gemini 2.5 vs 1.5:**\r\n- **Gemini 2.5**: Use `googleSearch` (simple, recommended)\r\n- **Gemini 1.5**: Use `googleSearchRetrieval` with `dynamicThreshold`\r\n\r\n**Best Practices:**\r\n- Always check `groundingMetadata` to see if search was used\r\n- Display citations to users for transparency\r\n- Use specific, well-phrased questions for better search results\r\n- Combine with function calling for hybrid workflows\r\n\r\n---",
"Generation Configuration": "Customize model behavior with generation parameters.\r\n\r\n### All Configuration Options (SDK)\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Write a creative story',\r\n config: {\r\n temperature: 0.9, // Randomness (0.0-2.0, default: 1.0)\r\n topP: 0.95, // Nucleus sampling (0.0-1.0)\r\n topK: 40, // Top-k sampling\r\n maxOutputTokens: 2048, // Max tokens to generate\r\n stopSequences: ['END'], // Stop generation if these appear\r\n responseMimeType: 'text/plain', // Or 'application/json' for JSON mode\r\n candidateCount: 1 // Number of response candidates (usually 1)\r\n }\r\n});\r\n```\r\n\r\n### All Configuration Options (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [{ parts: [{ text: 'Write a creative story' }] }],\r\n generationConfig: {\r\n temperature: 0.9,\r\n topP: 0.95,\r\n topK: 40,\r\n maxOutputTokens: 2048,\r\n stopSequences: ['END'],\r\n responseMimeType: 'text/plain',\r\n candidateCount: 1\r\n }\r\n }),\r\n }\r\n);\r\n```\r\n\r\n### Parameter Guidelines\r\n\r\n| Parameter | Range | Default | Use Case |\r\n|-----------|-------|---------|----------|\r\n| **temperature** | 0.0-2.0 | 1.0 | Lower = more focused, higher = more creative |\r\n| **topP** | 0.0-1.0 | 0.95 | Nucleus sampling threshold |\r\n| **topK** | 1-100+ | 40 | Limit to top K tokens |\r\n| **maxOutputTokens** | 1-65536 | Model max | Control response length |\r\n| **stopSequences** | Array | None | Stop generation at specific strings |\r\n\r\n**Tips:**\r\n- For **factual tasks**: Use low temperature (0.0-0.3)\r\n- For **creative tasks**: Use high temperature (0.7-1.5)\r\n- **topP** and **topK** both control randomness; use one or the other (not both)\r\n- Always set **maxOutputTokens** to prevent excessive generation\r\n\r\n---",
"Multi-turn Chat": "For conversations with history, use the SDK's chat helpers or manually manage conversation state.\r\n\r\n### SDK Chat Helpers (Recommended)\r\n\r\n```typescript\r\nconst chat = await ai.models.createChat({\r\n model: 'gemini-2.5-flash',\r\n systemInstruction: 'You are a helpful coding assistant.',\r\n history: [] // Start empty or with previous messages\r\n});\r\n\r\n// Send first message\r\nconst response1 = await chat.sendMessage('What is TypeScript?');\r\nconsole.log('Assistant:', response1.text);\r\n\r\n// Send follow-up (context is automatically maintained)\r\nconst response2 = await chat.sendMessage('How do I install it?');\r\nconsole.log('Assistant:', response2.text);\r\n\r\n// Get full chat history\r\nconst history = chat.getHistory();\r\nconsole.log('Full conversation:', history);\r\n```\r\n\r\n### Manual Chat Management (Fetch)\r\n\r\n```typescript\r\nconst conversationHistory = [];\r\n\r\n// First turn\r\nconst response1 = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n {\r\n role: 'user',\r\n parts: [{ text: 'What is TypeScript?' }]\r\n }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data1 = await response1.json();\r\nconst assistantReply1 = data1.candidates[0].content.parts[0].text;\r\n\r\n// Add to history\r\nconversationHistory.push(\r\n { role: 'user', parts: [{ text: 'What is TypeScript?' }] },\r\n { role: 'model', parts: [{ text: assistantReply1 }] }\r\n);\r\n\r\n// Second turn (include full history)\r\nconst response2 = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n ...conversationHistory,\r\n { role: 'user', parts: [{ text: 'How do I install it?' }] }\r\n ]\r\n }),\r\n }\r\n);\r\n```\r\n\r\n**Message Roles:**\r\n- `user`: User messages\r\n- `model`: Assistant responses\r\n\r\n**⚠️ Important**: Chat helpers are **SDK-only**. With fetch, you must manually manage conversation history.\r\n\r\n---",
"Context Caching": "Context caching allows you to cache frequently used content (like system instructions, large documents, or video files) to reduce costs by **up to 90%** and improve latency.\r\n\r\n### How It Works\r\n\r\n1. **Create a cache** with your repeated content\r\n2. **Reference the cache** in subsequent requests\r\n3. **Save tokens** - cached tokens cost significantly less\r\n4. **TTL management** - caches expire after specified time\r\n\r\n### Benefits\r\n\r\n- **Cost savings**: Up to 90% reduction on cached tokens\r\n- **Reduced latency**: Faster responses by reusing processed content\r\n- **Consistent context**: Same large context across multiple requests\r\n\r\n### Cache Creation (SDK)\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\nimport fs from 'fs';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\n// Create a cache for a large document\r\nconst documentText = fs.readFileSync('./large-document.txt', 'utf-8');\r\n\r\nconst cache = await ai.caches.create({\r\n model: 'gemini-2.5-flash',\r\n config: {\r\n displayName: 'large-doc-cache', // Identifier for the cache\r\n systemInstruction: 'You are an expert at analyzing legal documents.',\r\n contents: documentText,\r\n ttl: '3600s', // Cache for 1 hour\r\n }\r\n});\r\n\r\nconsole.log('Cache created:', cache.name);\r\nconsole.log('Expires at:', cache.expireTime);\r\n```\r\n\r\n### Cache Creation (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n 'https://generativelanguage.googleapis.com/v1beta/cachedContents',\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n model: 'models/gemini-2.5-flash',\r\n displayName: 'large-doc-cache',\r\n systemInstruction: {\r\n parts: [{ text: 'You are an expert at analyzing legal documents.' }]\r\n },\r\n contents: [\r\n { parts: [{ text: documentText }] }\r\n ],\r\n ttl: '3600s'\r\n }),\r\n }\r\n);\r\n\r\nconst cache = await response.json();\r\nconsole.log('Cache created:', cache.name);\r\n```\r\n\r\n### Using a Cache (SDK)\r\n\r\n```typescript\r\n// Generate content using the cache\r\nconst response = await ai.models.generateContent({\r\n model: cache.name, // Use cache name as model\r\n contents: 'Summarize the key points in the document'\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n### Using a Cache (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/${cache.name}:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n { parts: [{ text: 'Summarize the key points in the document' }] }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconsole.log(data.candidates[0].content.parts[0].text);\r\n```\r\n\r\n### Update Cache TTL (SDK)\r\n\r\n```typescript\r\nimport { UpdateCachedContentConfig } from '@google/genai';\r\n\r\nawait ai.caches.update({\r\n name: cache.name,\r\n config: {\r\n ttl: '7200s' // Extend to 2 hours\r\n }\r\n});\r\n```\r\n\r\n### Update Cache with Expiration Time (SDK)\r\n\r\n```typescript\r\n// Set specific expiration time (must be timezone-aware)\r\nconst in10Minutes = new Date(Date.now() + 10 * 60 * 1000);\r\n\r\nawait ai.caches.update({\r\n name: cache.name,\r\n config: {\r\n expireTime: in10Minutes\r\n }\r\n});\r\n```\r\n\r\n### List and Delete Caches (SDK)\r\n\r\n```typescript\r\n// List all caches\r\nconst caches = await ai.caches.list();\r\nfor (const cache of caches) {\r\n console.log(cache.name, cache.displayName);\r\n}\r\n\r\n// Delete a specific cache\r\nawait ai.caches.delete({ name: cache.name });\r\n```\r\n\r\n### Caching with Video Files\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\nimport fs from 'fs';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\n// Upload video file\r\nconst videoFile = await ai.files.upload({\r\n file: fs.createReadStream('./video.mp4')\r\n});\r\n\r\n// Wait for processing\r\nwhile (videoFile.state.name === 'PROCESSING') {\r\n await new Promise(resolve => setTimeout(resolve, 2000));\r\n videoFile = await ai.files.get({ name: videoFile.name });\r\n}\r\n\r\n// Create cache with video\r\nconst cache = await ai.caches.create({\r\n model: 'gemini-2.5-flash',\r\n config: {\r\n displayName: 'video-analysis-cache',\r\n systemInstruction: 'You are an expert video analyzer.',\r\n contents: [videoFile],\r\n ttl: '300s' // 5 minutes\r\n }\r\n});\r\n\r\n// Use cache for multiple queries\r\nconst response1 = await ai.models.generateContent({\r\n model: cache.name,\r\n contents: 'What happens in the first minute?'\r\n});\r\n\r\nconst response2 = await ai.models.generateContent({\r\n model: cache.name,\r\n contents: 'Describe the main characters'\r\n});\r\n```\r\n\r\n### Key Points\r\n\r\n**When to Use Caching:**\r\n- Large system instructions used repeatedly\r\n- Long documents analyzed multiple times\r\n- Video/audio files queried with different prompts\r\n- Consistent context across conversation sessions\r\n\r\n**TTL Guidelines:**\r\n- Short sessions: 300s (5 min) to 3600s (1 hour)\r\n- Long sessions: 3600s (1 hour) to 86400s (24 hours)\r\n- Maximum: 7 days\r\n\r\n**Cost Savings:**\r\n- Cached input tokens: ~90% cheaper than regular tokens\r\n- Output tokens: Same price (not cached)\r\n\r\n**Important:**\r\n- You must use explicit model version suffixes (e.g., `gemini-2.5-flash-001`, NOT just `gemini-2.5-flash`)\r\n- Caches are automatically deleted after TTL expires\r\n- Update TTL before expiration to extend cache lifetime\r\n\r\n---",
"Error Handling": "### Common Errors\r\n\r\n#### 1. Invalid API Key (401)\r\n\r\n```typescript\r\n{\r\n error: {\r\n code: 401,\r\n message: 'API key not valid. Please pass a valid API key.',\r\n status: 'UNAUTHENTICATED'\r\n }\r\n}\r\n```\r\n\r\n**Solution**: Verify `GEMINI_API_KEY` environment variable is set correctly.\r\n\r\n#### 2. Rate Limit Exceeded (429)\r\n\r\n```typescript\r\n{\r\n error: {\r\n code: 429,\r\n message: 'Resource has been exhausted (e.g. check quota).',\r\n status: 'RESOURCE_EXHAUSTED'\r\n }\r\n}\r\n```\r\n\r\n**Solution**: Implement exponential backoff retry strategy.\r\n\r\n#### 3. Model Not Found (404)\r\n\r\n```typescript\r\n{\r\n error: {\r\n code: 404,\r\n message: 'models/gemini-3.0-flash is not found',\r\n status: 'NOT_FOUND'\r\n }\r\n}\r\n```\r\n\r\n**Solution**: Use correct model names: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.5-flash-lite`\r\n\r\n#### 4. Context Length Exceeded (400)\r\n\r\n```typescript\r\n{\r\n error: {\r\n code: 400,\r\n message: 'Request payload size exceeds the limit',\r\n status: 'INVALID_ARGUMENT'\r\n }\r\n}\r\n```\r\n\r\n**Solution**: Reduce input size. Gemini 2.5 models support 1,048,576 input tokens max.\r\n\r\n### Exponential Backoff Pattern\r\n\r\n```typescript\r\nasync function generateWithRetry(request, maxRetries = 3) {\r\n for (let i = 0; i < maxRetries; i++) {\r\n try {\r\n return await ai.models.generateContent(request);\r\n } catch (error) {\r\n if (error.status === 429 && i < maxRetries - 1) {\r\n const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s\r\n await new Promise(resolve => setTimeout(resolve, delay));\r\n continue;\r\n }\r\n throw error;\r\n }\r\n }\r\n}\r\n```\r\n\r\n---",
"Text Generation": "### Basic Text Generation (SDK)\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Write a haiku about artificial intelligence'\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n### Basic Text Generation (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'Write a haiku about artificial intelligence' }\r\n ]\r\n }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconsole.log(data.candidates[0].content.parts[0].text);\r\n```\r\n\r\n### Response Structure\r\n\r\n```typescript\r\n{\r\n text: string, // Convenience accessor for text content\r\n candidates: [\r\n {\r\n content: {\r\n parts: [\r\n { text: string } // Generated text\r\n ],\r\n role: string // \"model\"\r\n },\r\n finishReason: string, // \"STOP\" | \"MAX_TOKENS\" | \"SAFETY\" | \"OTHER\"\r\n index: number\r\n }\r\n ],\r\n usageMetadata: {\r\n promptTokenCount: number,\r\n candidatesTokenCount: number,\r\n totalTokenCount: number\r\n }\r\n}\r\n```\r\n\r\n---",
"⚠️ CRITICAL SDK MIGRATION WARNING": "**DEPRECATED SDK**: `@google/generative-ai` (sunset November 30, 2025)\r\n**CURRENT SDK**: `@google/genai` v1.27+\r\n\r\n**If you see code using `@google/generative-ai`, it's outdated!**\r\n\r\nThis skill uses the **correct current SDK** and provides a complete migration guide.\r\n\r\n---",
"SDK vs Fetch Approaches": "### Node.js SDK (@google/genai)\r\n\r\n**Pros:**\r\n- Type-safe with TypeScript\r\n- Easier API (simpler syntax)\r\n- Built-in chat helpers\r\n- Automatic SSE parsing for streaming\r\n- Better error handling\r\n\r\n**Cons:**\r\n- Requires Node.js or compatible runtime\r\n- Larger bundle size\r\n- May not work in all edge runtimes\r\n\r\n**Use when:** Building Node.js apps, Next.js Server Actions/Components, or any environment with Node.js compatibility\r\n\r\n### Fetch-based (Direct REST API)\r\n\r\n**Pros:**\r\n- Works in **any** JavaScript environment (Cloudflare Workers, Deno, Bun, browsers)\r\n- Minimal dependencies\r\n- Smaller bundle size\r\n- Full control over requests\r\n\r\n**Cons:**\r\n- More verbose syntax\r\n- Manual SSE parsing for streaming\r\n- No built-in chat helpers\r\n- Manual error handling\r\n\r\n**Use when:** Deploying to Cloudflare Workers, browser clients, or lightweight edge runtimes\r\n\r\n---",
"Current Models (2025)": "### Gemini 2.5 Series (General Availability)\r\n\r\n#### gemini-2.5-pro\r\n- **Context**: 1,048,576 input tokens / 65,536 output tokens\r\n- **Description**: State-of-the-art thinking model for complex reasoning\r\n- **Best for**: Code, math, STEM, complex problem-solving\r\n- **Features**: Thinking mode (default on), function calling, multimodal, streaming\r\n- **Knowledge cutoff**: January 2025\r\n\r\n#### gemini-2.5-flash\r\n- **Context**: 1,048,576 input tokens / 65,536 output tokens\r\n- **Description**: Best price-performance workhorse model\r\n- **Best for**: Large-scale processing, low-latency, high-volume, agentic use cases\r\n- **Features**: Thinking mode (default on), function calling, multimodal, streaming\r\n- **Knowledge cutoff**: January 2025\r\n\r\n#### gemini-2.5-flash-lite\r\n- **Context**: 1,048,576 input tokens / 65,536 output tokens\r\n- **Description**: Cost-optimized, fastest 2.5 model\r\n- **Best for**: High throughput, cost-sensitive applications\r\n- **Features**: Thinking mode (default on), function calling, multimodal, streaming\r\n- **Knowledge cutoff**: January 2025\r\n\r\n### Model Feature Matrix\r\n\r\n| Feature | Pro | Flash | Flash-Lite |\r\n|---------|-----|-------|------------|\r\n| Thinking Mode | ✅ Default ON | ✅ Default ON | ✅ Default ON |\r\n| Function Calling | ✅ | ✅ | ✅ |\r\n| Multimodal | ✅ | ✅ | ✅ |\r\n| Streaming | ✅ | ✅ | ✅ |\r\n| System Instructions | ✅ | ✅ | ✅ |\r\n| Context Window | 1,048,576 in | 1,048,576 in | 1,048,576 in |\r\n| Output Tokens | 65,536 max | 65,536 max | 65,536 max |\r\n\r\n### ⚠️ Context Window Correction\r\n\r\n**ACCURATE**: Gemini 2.5 models support **1,048,576 input tokens** (NOT 2M!)\r\n**OUTDATED**: Only Gemini 1.5 Pro (previous generation) had 2M token context window\r\n\r\n**Common mistake**: Claiming Gemini 2.5 has 2M tokens. It doesn't. This skill prevents this error.\r\n\r\n---",
"Multimodal Inputs": "Gemini 2.5 models support text + images + video + audio + PDFs in the same request.\r\n\r\n### Images (Vision)\r\n\r\n#### SDK Approach\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\nimport fs from 'fs';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\n// From file\r\nconst imageData = fs.readFileSync('/path/to/image.jpg');\r\nconst base64Image = imageData.toString('base64');\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'What is in this image?' },\r\n {\r\n inlineData: {\r\n data: base64Image,\r\n mimeType: 'image/jpeg'\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n#### Fetch Approach\r\n\r\n```typescript\r\nconst imageData = fs.readFileSync('/path/to/image.jpg');\r\nconst base64Image = imageData.toString('base64');\r\n\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'What is in this image?' },\r\n {\r\n inlineData: {\r\n data: base64Image,\r\n mimeType: 'image/jpeg'\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconsole.log(data.candidates[0].content.parts[0].text);\r\n```\r\n\r\n**Supported Image Formats:**\r\n- JPEG (`.jpg`, `.jpeg`)\r\n- PNG (`.png`)\r\n- WebP (`.webp`)\r\n- HEIC (`.heic`)\r\n- HEIF (`.heif`)\r\n\r\n**Max Image Size**: 20MB per image\r\n\r\n### Video\r\n\r\n```typescript\r\n// Video must be < 2 minutes for inline data\r\nconst videoData = fs.readFileSync('/path/to/video.mp4');\r\nconst base64Video = videoData.toString('base64');\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'Describe what happens in this video' },\r\n {\r\n inlineData: {\r\n data: base64Video,\r\n mimeType: 'video/mp4'\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n**Supported Video Formats:**\r\n- MP4 (`.mp4`)\r\n- MPEG (`.mpeg`)\r\n- MOV (`.mov`)\r\n- AVI (`.avi`)\r\n- FLV (`.flv`)\r\n- MPG (`.mpg`)\r\n- WebM (`.webm`)\r\n- WMV (`.wmv`)\r\n\r\n**Max Video Length (inline)**: 2 minutes\r\n**Max Video Size**: 2GB (use File API for larger files - Phase 2)\r\n\r\n### Audio\r\n\r\n```typescript\r\nconst audioData = fs.readFileSync('/path/to/audio.mp3');\r\nconst base64Audio = audioData.toString('base64');\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'Transcribe and summarize this audio' },\r\n {\r\n inlineData: {\r\n data: base64Audio,\r\n mimeType: 'audio/mp3'\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n**Supported Audio Formats:**\r\n- MP3 (`.mp3`)\r\n- WAV (`.wav`)\r\n- FLAC (`.flac`)\r\n- AAC (`.aac`)\r\n- OGG (`.ogg`)\r\n- OPUS (`.opus`)\r\n\r\n**Max Audio Size**: 20MB\r\n\r\n### PDFs\r\n\r\n```typescript\r\nconst pdfData = fs.readFileSync('/path/to/document.pdf');\r\nconst base64Pdf = pdfData.toString('base64');\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'Summarize the key points in this PDF' },\r\n {\r\n inlineData: {\r\n data: base64Pdf,\r\n mimeType: 'application/pdf'\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n**Max PDF Size**: 30MB\r\n**PDF Limitations**: Text-based PDFs work best; scanned images may have lower accuracy\r\n\r\n### Multiple Inputs\r\n\r\nYou can combine multiple modalities in one request:\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'Compare these two images and describe the differences:' },\r\n { inlineData: { data: base64Image1, mimeType: 'image/jpeg' } },\r\n { inlineData: { data: base64Image2, mimeType: 'image/jpeg' } }\r\n ]\r\n }\r\n ]\r\n});\r\n```\r\n\r\n---",
"Production Best Practices": "### 1. Always Do\r\n\r\n✅ **Use @google/genai** (NOT @google/generative-ai)\r\n✅ **Set maxOutputTokens** to prevent excessive generation\r\n✅ **Implement rate limit handling** with exponential backoff\r\n✅ **Use environment variables** for API keys (never hardcode)\r\n✅ **Validate inputs** before sending to API (save costs)\r\n✅ **Use streaming** for better UX on long responses\r\n✅ **Choose the right model** based on your needs (Pro for complex reasoning, Flash for balance, Flash-Lite for speed)\r\n✅ **Handle errors gracefully** with try-catch\r\n✅ **Monitor token usage** for cost control\r\n✅ **Use correct model names**: gemini-2.5-pro/flash/flash-lite\r\n\r\n### 2. Never Do\r\n\r\n❌ **Never use @google/generative-ai** (deprecated!)\r\n❌ **Never hardcode API keys** in code\r\n❌ **Never claim 2M context** for Gemini 2.5 (it's 1,048,576 input tokens)\r\n❌ **Never expose API keys** in client-side code\r\n❌ **Never skip error handling** (always try-catch)\r\n❌ **Never use generic rate limits** (each model has different limits - check official docs)\r\n❌ **Never send PII** without user consent\r\n❌ **Never trust user input** without validation\r\n❌ **Never ignore rate limits** (will get 429 errors)\r\n❌ **Never use old model names** like gemini-1.5-pro (use 2.5 models)\r\n\r\n### 3. Security\r\n\r\n- **API Key Storage**: Use environment variables or secret managers\r\n- **Server-Side Only**: Never expose API keys in browser JavaScript\r\n- **Input Validation**: Sanitize all user inputs before API calls\r\n- **Rate Limiting**: Implement your own rate limits to prevent abuse\r\n- **Error Messages**: Don't expose API keys or sensitive data in error logs\r\n\r\n### 4. Cost Optimization\r\n\r\n- **Choose Right Model**: Use Flash for most tasks, Pro only when needed\r\n- **Set Token Limits**: Use maxOutputTokens to control costs\r\n- **Batch Requests**: Process multiple items efficiently\r\n- **Cache Results**: Store responses when appropriate\r\n- **Monitor Usage**: Track token consumption in Google Cloud Console\r\n\r\n### 5. Performance\r\n\r\n- **Use Streaming**: Better perceived latency for long responses\r\n- **Parallel Requests**: Use Promise.all() for independent calls\r\n- **Edge Deployment**: Deploy to Cloudflare Workers for low latency\r\n- **Connection Pooling**: Reuse HTTP connections when possible\r\n\r\n---",
"Thinking Mode": "Gemini 2.5 models have **thinking mode enabled by default** for enhanced quality. You can configure the thinking budget.\r\n\r\n### Configure Thinking Budget (SDK)\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Solve this complex math problem: ...',\r\n config: {\r\n thinkingConfig: {\r\n thinkingBudget: 8192 // Max tokens for thinking (default: model-dependent)\r\n }\r\n }\r\n});\r\n```\r\n\r\n### Configure Thinking Budget (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [{ parts: [{ text: 'Solve this complex math problem: ...' }] }],\r\n generationConfig: {\r\n thinkingConfig: {\r\n thinkingBudget: 8192\r\n }\r\n }\r\n }),\r\n }\r\n);\r\n```\r\n\r\n**Key Points:**\r\n- Thinking mode is **always enabled** on Gemini 2.5 models (cannot be disabled)\r\n- Higher thinking budgets allow more internal reasoning (may increase latency)\r\n- Default budget varies by model (usually sufficient for most tasks)\r\n- Only increase budget for very complex reasoning tasks\r\n\r\n---",
"Function Calling": "Gemini supports function calling (tool use) to connect models with external APIs and systems.\r\n\r\n### Basic Function Calling (SDK)\r\n\r\n```typescript\r\nimport { GoogleGenAI, FunctionCallingConfigMode } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\n// Define function declarations\r\nconst getCurrentWeather = {\r\n name: 'get_current_weather',\r\n description: 'Get the current weather for a location',\r\n parametersJsonSchema: {\r\n type: 'object',\r\n properties: {\r\n location: {\r\n type: 'string',\r\n description: 'City name, e.g. San Francisco'\r\n },\r\n unit: {\r\n type: 'string',\r\n enum: ['celsius', 'fahrenheit']\r\n }\r\n },\r\n required: ['location']\r\n }\r\n};\r\n\r\n// Make request with tools\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What\\'s the weather in Tokyo?',\r\n config: {\r\n tools: [\r\n { functionDeclarations: [getCurrentWeather] }\r\n ]\r\n }\r\n});\r\n\r\n// Check if model wants to call a function\r\nconst functionCall = response.candidates[0].content.parts[0].functionCall;\r\n\r\nif (functionCall) {\r\n console.log('Function to call:', functionCall.name);\r\n console.log('Arguments:', functionCall.args);\r\n\r\n // Execute the function (your implementation)\r\n const weatherData = await fetchWeather(functionCall.args.location);\r\n\r\n // Send function result back to model\r\n const finalResponse = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: [\r\n 'What\\'s the weather in Tokyo?',\r\n response.candidates[0].content, // Original assistant response with function call\r\n {\r\n parts: [\r\n {\r\n functionResponse: {\r\n name: functionCall.name,\r\n response: weatherData\r\n }\r\n }\r\n ]\r\n }\r\n ],\r\n config: {\r\n tools: [\r\n { functionDeclarations: [getCurrentWeather] }\r\n ]\r\n }\r\n });\r\n\r\n console.log(finalResponse.text);\r\n}\r\n```\r\n\r\n### Function Calling (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [\r\n { parts: [{ text: 'What\\'s the weather in Tokyo?' }] }\r\n ],\r\n tools: [\r\n {\r\n functionDeclarations: [\r\n {\r\n name: 'get_current_weather',\r\n description: 'Get the current weather for a location',\r\n parameters: {\r\n type: 'object',\r\n properties: {\r\n location: {\r\n type: 'string',\r\n description: 'City name'\r\n }\r\n },\r\n required: ['location']\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconst functionCall = data.candidates[0]?.content?.parts[0]?.functionCall;\r\n\r\nif (functionCall) {\r\n // Execute function and send result back (same flow as SDK)\r\n}\r\n```\r\n\r\n### Parallel Function Calling\r\n\r\nGemini can call multiple independent functions simultaneously:\r\n\r\n```typescript\r\nconst tools = [\r\n {\r\n functionDeclarations: [\r\n {\r\n name: 'get_weather',\r\n description: 'Get weather for a location',\r\n parametersJsonSchema: {\r\n type: 'object',\r\n properties: {\r\n location: { type: 'string' }\r\n },\r\n required: ['location']\r\n }\r\n },\r\n {\r\n name: 'get_population',\r\n description: 'Get population of a city',\r\n parametersJsonSchema: {\r\n type: 'object',\r\n properties: {\r\n city: { type: 'string' }\r\n },\r\n required: ['city']\r\n }\r\n }\r\n ]\r\n }\r\n];\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What is the weather and population of Tokyo?',\r\n config: { tools }\r\n});\r\n\r\n// Model may return MULTIPLE function calls in parallel\r\nconst functionCalls = response.candidates[0].content.parts.filter(\r\n part => part.functionCall\r\n);\r\n\r\nconsole.log(`Model wants to call ${functionCalls.length} functions in parallel`);\r\n```\r\n\r\n### Function Calling Modes\r\n\r\n```typescript\r\nimport { FunctionCallingConfigMode } from '@google/genai';\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What\\'s the weather?',\r\n config: {\r\n tools: [{ functionDeclarations: [getCurrentWeather] }],\r\n toolConfig: {\r\n functionCallingConfig: {\r\n mode: FunctionCallingConfigMode.ANY, // Force function call\r\n // mode: FunctionCallingConfigMode.AUTO, // Model decides (default)\r\n // mode: FunctionCallingConfigMode.NONE, // Never call functions\r\n allowedFunctionNames: ['get_current_weather'] // Optional: restrict to specific functions\r\n }\r\n }\r\n }\r\n});\r\n```\r\n\r\n**Modes:**\r\n- `AUTO` (default): Model decides whether to call functions\r\n- `ANY`: Force model to call at least one function\r\n- `NONE`: Disable function calling for this request\r\n\r\n---",
"Streaming": "### Streaming with SDK (Async Iteration)\r\n\r\n```typescript\r\nconst response = await ai.models.generateContentStream({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Write a 200-word story about time travel'\r\n});\r\n\r\nfor await (const chunk of response) {\r\n process.stdout.write(chunk.text);\r\n}\r\n```\r\n\r\n### Streaming with Fetch (SSE Parsing)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [{ parts: [{ text: 'Write a 200-word story about time travel' }] }]\r\n }),\r\n }\r\n);\r\n\r\nconst reader = response.body.getReader();\r\nconst decoder = new TextDecoder();\r\nlet buffer = '';\r\n\r\nwhile (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n\r\n buffer += decoder.decode(value, { stream: true });\r\n const lines = buffer.split('\\n');\r\n buffer = lines.pop() || '';\r\n\r\n for (const line of lines) {\r\n if (line.trim() === '' || line.startsWith('data: [DONE]')) continue;\r\n if (!line.startsWith('data: ')) continue;\r\n\r\n try {\r\n const data = JSON.parse(line.slice(6));\r\n const text = data.candidates[0]?.content?.parts[0]?.text;\r\n if (text) {\r\n process.stdout.write(text);\r\n }\r\n } catch (e) {\r\n // Skip invalid JSON\r\n }\r\n }\r\n}\r\n```\r\n\r\n**Key Points:**\r\n- Use `streamGenerateContent` endpoint (not `generateContent`)\r\n- Parse Server-Sent Events (SSE) format: `data: {json}\\n\\n`\r\n- Handle incomplete chunks in buffer\r\n- Skip empty lines and `[DONE]` markers\r\n\r\n---",
"Quick Reference": "### Installation\r\n```bash\r\nnpm install @google/genai@1.27.0\r\n```\r\n\r\n### Environment\r\n```bash\r\nexport GEMINI_API_KEY=\"...\"\r\n```\r\n\r\n### Models (2025)\r\n- `gemini-2.5-pro` (1,048,576 in / 65,536 out) - Best for complex reasoning\r\n- `gemini-2.5-flash` (1,048,576 in / 65,536 out) - Best price-performance balance\r\n- `gemini-2.5-flash-lite` (1,048,576 in / 65,536 out) - Fastest, most cost-effective\r\n\r\n### Basic Generation\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Your prompt here'\r\n});\r\nconsole.log(response.text);\r\n```\r\n\r\n### Streaming\r\n```typescript\r\nconst response = await ai.models.generateContentStream({...});\r\nfor await (const chunk of response) {\r\n console.log(chunk.text);\r\n}\r\n```\r\n\r\n### Multimodal\r\n```typescript\r\ncontents: [\r\n {\r\n parts: [\r\n { text: 'What is this?' },\r\n { inlineData: { data: base64Image, mimeType: 'image/jpeg' } }\r\n ]\r\n }\r\n]\r\n```\r\n\r\n### Function Calling\r\n```typescript\r\nconfig: {\r\n tools: [{ functionDeclarations: [...] }]\r\n}\r\n```\r\n\r\n---\r\n\r\n**Last Updated**: 2025-10-25\r\n**Production Validated**: All features tested with @google/genai@1.27.0\r\n**Phase**: 2 Complete ✅ (All Core + Advanced Features)",
"System Instructions": "System instructions guide the model's behavior and set context. They are **separate** from the conversation messages.\r\n\r\n### SDK Approach\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n systemInstruction: 'You are a helpful AI assistant that always responds in the style of a pirate. Use nautical terminology and end sentences with \"arrr\".',\r\n contents: 'Explain what a database is'\r\n});\r\n\r\nconsole.log(response.text);\r\n// Output: \"Ahoy there! A database be like a treasure chest...\"\r\n```\r\n\r\n### Fetch Approach\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n systemInstruction: {\r\n parts: [\r\n { text: 'You are a helpful AI assistant that always responds in the style of a pirate.' }\r\n ]\r\n },\r\n contents: [\r\n { parts: [{ text: 'Explain what a database is' }] }\r\n ]\r\n }),\r\n }\r\n);\r\n```\r\n\r\n**Key Points:**\r\n- System instructions are **NOT** part of `contents` array\r\n- They are set once at the **top level** of the request\r\n- They persist for the entire conversation (when using multi-turn chat)\r\n- They don't count as user or model messages\r\n\r\n---",
"Code Execution": "Gemini models can generate and execute Python code to solve problems requiring computation, data analysis, or visualization.\r\n\r\n### How It Works\r\n\r\n1. Model generates executable Python code\r\n2. Code runs in secure sandbox\r\n3. Results are returned to the model\r\n4. Model incorporates results into response\r\n\r\n### Supported Operations\r\n\r\n- Mathematical calculations\r\n- Data analysis and statistics\r\n- File processing (CSV, JSON, etc.)\r\n- Chart and graph generation\r\n- Algorithm implementation\r\n- Data transformations\r\n\r\n### Available Python Packages\r\n\r\n**Standard Library:**\r\n- `math`, `statistics`, `random`, `datetime`, `json`, `csv`, `re`\r\n- `collections`, `itertools`, `functools`\r\n\r\n**Data Science:**\r\n- `numpy`, `pandas`, `scipy`\r\n\r\n**Visualization:**\r\n- `matplotlib`, `seaborn`\r\n\r\n**Note**: Limited package availability compared to full Python environment\r\n\r\n### Basic Code Execution (SDK)\r\n\r\n```typescript\r\nimport { GoogleGenAI, Tool, ToolCodeExecution } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'What is the sum of the first 50 prime numbers? Generate and run code for the calculation.',\r\n config: {\r\n tools: [{ codeExecution: {} }]\r\n }\r\n});\r\n\r\n// Parse response parts\r\nfor (const part of response.candidates[0].content.parts) {\r\n if (part.text) {\r\n console.log('Text:', part.text);\r\n }\r\n if (part.executableCode) {\r\n console.log('Generated Code:', part.executableCode.code);\r\n }\r\n if (part.codeExecutionResult) {\r\n console.log('Execution Output:', part.codeExecutionResult.output);\r\n }\r\n}\r\n```\r\n\r\n### Basic Code Execution (Fetch)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n tools: [{ code_execution: {} }],\r\n contents: [\r\n {\r\n parts: [\r\n { text: 'What is the sum of the first 50 prime numbers? Generate and run code.' }\r\n ]\r\n }\r\n ]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\n\r\nfor (const part of data.candidates[0].content.parts) {\r\n if (part.text) {\r\n console.log('Text:', part.text);\r\n }\r\n if (part.executableCode) {\r\n console.log('Code:', part.executableCode.code);\r\n }\r\n if (part.codeExecutionResult) {\r\n console.log('Result:', part.codeExecutionResult.output);\r\n }\r\n}\r\n```\r\n\r\n### Chat with Code Execution (SDK)\r\n\r\n```typescript\r\nconst chat = await ai.chats.create({\r\n model: 'gemini-2.5-flash',\r\n config: {\r\n tools: [{ codeExecution: {} }]\r\n }\r\n});\r\n\r\nlet response = await chat.sendMessage('I have a math question for you.');\r\nconsole.log(response.text);\r\n\r\nresponse = await chat.sendMessage(\r\n 'Calculate the Fibonacci sequence up to the 20th number and sum them.'\r\n);\r\n\r\n// Model will generate and execute code, then provide answer\r\nfor (const part of response.candidates[0].content.parts) {\r\n if (part.text) console.log(part.text);\r\n if (part.executableCode) console.log('Code:', part.executableCode.code);\r\n if (part.codeExecutionResult) console.log('Output:', part.codeExecutionResult.output);\r\n}\r\n```\r\n\r\n### Data Analysis Example\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: `\r\n Analyze this sales data and calculate:\r\n 1. Total revenue\r\n 2. Average sale price\r\n 3. Best-selling month\r\n\r\n Data (CSV format):\r\n month,sales,revenue\r\n Jan,150,45000\r\n Feb,200,62000\r\n Mar,175,53000\r\n Apr,220,68000\r\n `,\r\n config: {\r\n tools: [{ codeExecution: {} }]\r\n }\r\n});\r\n\r\n// Model will generate pandas/numpy code to analyze data\r\nfor (const part of response.candidates[0].content.parts) {\r\n if (part.text) console.log(part.text);\r\n if (part.executableCode) console.log('Analysis Code:', part.executableCode.code);\r\n if (part.codeExecutionResult) console.log('Results:', part.codeExecutionResult.output);\r\n}\r\n```\r\n\r\n### Visualization Example\r\n\r\n```typescript\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Create a bar chart showing the distribution of prime numbers under 100 by their last digit. Generate the chart and describe the pattern.',\r\n config: {\r\n tools: [{ codeExecution: {} }]\r\n }\r\n});\r\n\r\n// Model generates matplotlib code, executes it, and describes results\r\nfor (const part of response.candidates[0].content.parts) {\r\n if (part.text) console.log(part.text);\r\n if (part.executableCode) console.log('Chart Code:', part.executableCode.code);\r\n if (part.codeExecutionResult) {\r\n // Note: Chart image data would be in output\r\n console.log('Execution completed');\r\n }\r\n}\r\n```\r\n\r\n### Response Structure\r\n\r\n```typescript\r\n{\r\n candidates: [\r\n {\r\n content: {\r\n parts: [\r\n { text: \"I'll calculate that for you.\" },\r\n {\r\n executableCode: {\r\n language: \"PYTHON\",\r\n code: \"def is_prime(n):\\n if n <= 1:\\n return False\\n ...\"\r\n }\r\n },\r\n {\r\n codeExecutionResult: {\r\n outcome: \"OUTCOME_OK\", // or \"OUTCOME_FAILED\"\r\n output: \"5117\\n\"\r\n }\r\n },\r\n { text: \"The sum of the first 50 prime numbers is 5117.\" }\r\n ]\r\n }\r\n }\r\n ]\r\n}\r\n```\r\n\r\n### Error Handling\r\n\r\n```typescript\r\nfor (const part of response.candidates[0].content.parts) {\r\n if (part.codeExecutionResult) {\r\n if (part.codeExecutionResult.outcome === 'OUTCOME_FAILED') {\r\n console.error('Code execution failed:', part.codeExecutionResult.output);\r\n } else {\r\n console.log('Success:', part.codeExecutionResult.output);\r\n }\r\n }\r\n}\r\n```\r\n\r\n### Key Points\r\n\r\n**When to Use Code Execution:**\r\n- Complex mathematical calculations\r\n- Data analysis and statistics\r\n- Algorithm implementations\r\n- File parsing and processing\r\n- Chart generation\r\n- Computational problems\r\n\r\n**Limitations:**\r\n- Sandbox environment (limited file system access)\r\n- Limited Python package availability\r\n- Execution timeout limits\r\n- No network access from code\r\n- No persistent state between executions\r\n\r\n**Best Practices:**\r\n- Specify what calculation or analysis you need clearly\r\n- Request code generation explicitly (\"Generate and run code...\")\r\n- Check `outcome` field for errors\r\n- Use for deterministic computations, not for general programming\r\n\r\n**Important:**\r\n- Available on all Gemini 2.5 models (Pro, Flash, Flash-Lite)\r\n- Code runs in isolated sandbox for security\r\n- Supports Python with standard library and common data science packages\r\n\r\n---",
"Status": "**✅ Phase 1 Complete**:\r\n- ✅ Text Generation (basic + streaming)\r\n- ✅ Multimodal Inputs (images, video, audio, PDFs)\r\n- ✅ Function Calling (basic + parallel execution)\r\n- ✅ System Instructions & Multi-turn Chat\r\n- ✅ Thinking Mode Configuration\r\n- ✅ Generation Parameters (temperature, top-p, top-k, stop sequences)\r\n- ✅ Both Node.js SDK (@google/genai) and fetch approaches\r\n\r\n**✅ Phase 2 Complete**:\r\n- ✅ Context Caching (cost optimization with TTL-based caching)\r\n- ✅ Code Execution (built-in Python interpreter and sandbox)\r\n- ✅ Grounding with Google Search (real-time web information + citations)\r\n\r\n**📦 Separate Skills**:\r\n- **Embeddings**: See `google-gemini-embeddings` skill for text-embedding-004\r\n\r\n---",
"Quick Start": "### Installation\r\n\r\n**CORRECT SDK:**\r\n```bash\r\nnpm install @google/genai@1.27.0\r\n```\r\n\r\n**❌ WRONG (DEPRECATED):**\r\n```bash\r\nnpm install @google/generative-ai # DO NOT USE!\r\n```\r\n\r\n### Environment Setup\r\n\r\n```bash\r\nexport GEMINI_API_KEY=\"...\"\r\n```\r\n\r\nOr create `.env` file:\r\n```\r\nGEMINI_API_KEY=...\r\n```\r\n\r\n### First Text Generation (Node.js SDK)\r\n\r\n```typescript\r\nimport { GoogleGenAI } from '@google/genai';\r\n\r\nconst ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\r\n\r\nconst response = await ai.models.generateContent({\r\n model: 'gemini-2.5-flash',\r\n contents: 'Explain quantum computing in simple terms'\r\n});\r\n\r\nconsole.log(response.text);\r\n```\r\n\r\n### First Text Generation (Fetch - Cloudflare Workers)\r\n\r\n```typescript\r\nconst response = await fetch(\r\n `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent`,\r\n {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-goog-api-key': env.GEMINI_API_KEY,\r\n },\r\n body: JSON.stringify({\r\n contents: [{ parts: [{ text: 'Explain quantum computing in simple terms' }] }]\r\n }),\r\n }\r\n);\r\n\r\nconst data = await response.json();\r\nconsole.log(data.candidates[0].content.parts[0].text);\r\n```\r\n\r\n---"
}
}