chrome-ai-extension
npx skills add https://github.com/vibecodersph/gemini-nano-chrome-extension-skill --skill chrome-ai-extension
Agent 安装分布
Skill 文档
Chrome AI Extension Skill
Create Chrome extensions that leverage Chrome’s built-in AI capabilities for on-device machine learning without external API calls.
Chrome AI APIs Overview
Chrome provides several built-in AI APIs that run locally on-device:
- LanguageModel API (Prompt API): General-purpose LLM for conversational AI and text generation using Gemini Nano
- Summarization API: Specialized for text summarization
- Translation API: Language translation
- Writer API: Assisted writing and content generation
Note: The API is experimental and evolving. In current Chromium builds the exposed surface for extensions is the global LanguageModel object inside page contexts (content scripts, popups, etc.); the chrome.ai namespace is not wired up for service workers yet.
Quick Start – Working Example
Here’s a working pattern that matches what currently ships in Canary/Dev (127+):
// content.js - injected into the page
let aiSession = null;
async function ensureSession() {
if (!('LanguageModel' in self)) {
throw new Error('Chrome on-device AI not available');
}
if (aiSession) {
return aiSession;
}
aiSession = await LanguageModel.create({
temperature: 0.7,
topK: 3,
systemPrompt: 'You are a helpful assistant.'
});
return aiSession;
}
async function askQuestion(question) {
const session = await ensureSession();
return session.prompt(question);
}
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'ask') {
askQuestion(message.question)
.then(response => sendResponse({ success: true, response }))
.catch(error => sendResponse({ success: false, error: error.message }));
return true; // async response
}
});
Quick Start Workflow
- Check API Availability: Always verify API availability before use
- Request Capabilities: Check if the user’s browser supports the features
- Create Session: Initialize an AI session
- Interact: Use the session for AI operations
- Handle Errors: Gracefully handle unavailable features
Extension Architecture
Manifest Configuration
Use Manifest V3 with appropriate permissions:
{
"manifest_version": 3,
"name": "My AI Extension",
"version": "1.0.0",
"permissions": ["storage"],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
}
}
Note: Request "aiLanguageModel" in permissions or the API will not appear to the extension, even on Canary/Dev builds. Add any additional permissions (e.g., activeTab, storage) your feature set requires.
File Structure
Standard Chrome extension structure:
extension/
âââ manifest.json
âââ background.js (service worker)
âââ popup.html
âââ popup.js
âââ content.js (if needed)
âââ styles.css
API Usage Patterns
Prompt API / LanguageModel API
The Prompt API provides conversational AI capabilities using Gemini Nano.
Current API Pattern (LanguageModel global)
IMPORTANT: In page-context scripts (content scripts, popups, option pages) the stable entry point is the global LanguageModel. The chrome.ai namespace is not exposed to service workers today.
Availability Check:
if (!('LanguageModel' in self)) {
// API not available
}
const capabilities = await LanguageModel.capabilities?.();
// Returns: { available: "readily" | "after-download" | "no" }
Create Session with System Prompt:
const session = await LanguageModel.create({
temperature: 0.7,
topK: 3,
systemPrompt: 'You are a helpful assistant...'
});
Note: Use systemPrompt (not initialPrompts or outputLanguage).
Generate Response:
// Non-streaming
const response = await session.prompt("Your prompt here");
// Streaming (if supported)
if (session.promptStreaming) {
const stream = await session.promptStreaming("Your prompt here");
let result = '';
let previous = '';
for await (const chunk of stream) {
const fragment = chunk.startsWith(previous) ? chunk.slice(previous.length) : chunk;
result += fragment;
previous = chunk;
}
}
Destroy Session:
if (session.destroy) {
session.destroy();
}
Fallback API Pattern (window.ai / chrome.ai)
Some experimental builds briefly exposed the API under window.ai.languageModel or chrome.ai.languageModel. If you must support those variants, probe them after checking the global:
const candidates = [
self.LanguageModel,
window?.ai?.languageModel,
chrome?.ai?.languageModel
].filter(Boolean);
const provider = candidates.find(p => typeof p.create === 'function');
if (!provider) {
throw new Error('No on-device language model API found');
}
const session = await provider.create({ temperature: 0.7, topK: 3 });
Summarization API
Specialized for text summarization.
Check Availability:
const canSummarize = await window.ai?.summarizer?.capabilities();
Create Summarizer:
const summarizer = await window.ai.summarizer.create({
type: 'tl;dr', // or 'key-points', 'teaser', 'headline'
length: 'short' // or 'medium', 'long'
});
Summarize Text:
const summary = await summarizer.summarize(longText);
Translation API
For language translation tasks.
Check Availability:
const canTranslate = await window.ai?.translator?.capabilities();
Create Translator:
const translator = await window.ai.translator.create({
sourceLanguage: 'en',
targetLanguage: 'es'
});
Translate Text:
const translated = await translator.translate('Hello, world!');
Writer API
For assisted writing and content generation.
Check Availability:
const canWrite = await window.ai?.writer?.capabilities();
Create Writer:
const writer = await window.ai.writer.create({
tone: 'formal', // or 'casual', 'neutral'
length: 'medium'
});
Generate Content:
const content = await writer.write('Write about...');
Common Patterns
Robust JSON Parsing
AI models may return malformed JSON. Use multi-layer parsing:
function sanitizeModelJson(text) {
let cleaned = text.trim();
// Remove markdown code blocks
if (cleaned.startsWith('```')) {
cleaned = cleaned.replace(/^```(?:json)?/i, '').replace(/```$/i, '').trim();
}
// Extract JSON object
const firstBrace = cleaned.indexOf('{');
const lastBrace = cleaned.lastIndexOf('}');
if (firstBrace !== -1 && lastBrace !== -1 && lastBrace > firstBrace) {
cleaned = cleaned.slice(firstBrace, lastBrace + 1).trim();
}
return cleaned;
}
function parseModelResponse(raw) {
const cleaned = sanitizeModelJson(raw);
try {
return JSON.parse(cleaned);
} catch (error) {
console.warn('Failed to parse model JSON', { raw, cleaned }, error);
throw new Error('Model returned malformed JSON. Try again.');
}
}
Reusable Prompt Helper
Handle both streaming and non-streaming sessions:
async function runPrompt(session, prompt) {
// Try non-streaming first
if (session.prompt) {
return await session.prompt(prompt);
}
// Fall back to streaming
if (session.promptStreaming) {
const stream = await session.promptStreaming(prompt);
let result = '';
let previous = '';
for await (const chunk of stream) {
// Handle incremental chunks
const fragment = chunk.startsWith(previous)
? chunk.slice(previous.length)
: chunk;
result += fragment;
previous = chunk;
}
return result;
}
throw new Error('Prompt API shape not supported');
}
Error Handling
Always handle cases where APIs are unavailable:
async function initializeAI() {
try {
if (!('LanguageModel' in self)) {
return { error: 'Chrome AI API not available in this context' };
}
const capabilities = typeof LanguageModel.capabilities === 'function'
? await LanguageModel.capabilities()
: null;
if (capabilities) {
if (capabilities.available === 'no') {
return { error: 'AI not available on this device' };
}
if (capabilities.available === 'after-download') {
return { error: 'AI model needs to be downloaded first. Check chrome://components' };
}
}
const session = await LanguageModel.create({
temperature: 0.7,
topK: 3,
systemPrompt: 'You are a helpful assistant.'
});
return { session };
} catch (error) {
return { error: error.message };
}
}
Background Script Communication
Service workers currently do not get the LanguageModel API. If you need background coordination, have the background script forward requests to a page-context script (content script, popup, or options page) that actually calls LanguageModel.create().
Content Script Integration
Interact with page content using content scripts:
// Get selected text from page
const selectedText = window.getSelection().toString();
// Send to background for AI processing
chrome.runtime.sendMessage({
action: 'summarize',
text: selectedText
});
Best Practices
- Always check availability before attempting to use AI features
- Handle gracefully when features are unavailable
- Destroy sessions when done to free resources
- Use streaming for long responses to improve UX
- Cache sessions when making multiple requests with same config
- Provide fallbacks for browsers without AI support
- Monitor token limits – sessions have context limits
- Run AI calls in page contexts â service workers currently lack the API surface
- Test across Chrome versions – AI features are experimental
Debugging
Enable Chrome Flags
- Navigate to
chrome://flags - Enable:
#prompt-api-for-gemini-nano - Enable:
#optimization-guide-on-device-modelâ Enabled BypassPerfRequirement - Restart Chrome completely
Download Gemini Nano Model
- Visit
chrome://components - Look for “Optimization Guide On Device Model”
- Click “Check for update”
- Wait for download (~1.7GB)
- Status should show “Up to date”
Verify API Availability
Open DevTools Console (F12) on any page:
// Check capabilities
await LanguageModel.capabilities?.()
// Should return: { available: "readily" }
// If "after-download", wait a few minutes after download completes
Requirements
- Chrome Canary or Dev channel (version 127+)
- ~1.7GB disk space for Gemini Nano model
- Supported hardware (most modern systems)
Common Use Cases
- Text summarization for articles
- Translation of web content
- Writing assistance and suggestions
- Conversational chatbots
- Content generation
- Text analysis and insights
Reference Files
For detailed examples and patterns:
- references/battle-tested-patterns.md: Production-proven patterns from real Chrome AI extensions
- references/api-examples.md: Complete working examples for each API
- references/extension-patterns.md: Common extension architecture patterns
- assets/template/: Basic extension template to start from
Limitations
- Chrome AI is experimental and API surface may change
- Requires Chrome Canary or Dev channel (version 127+)
- Model must be downloaded (~1.7GB – happens automatically)
- Rate limits and context length restrictions apply
- Not all devices support all features
- Currently supports English, Spanish, and Japanese output
- Quality may vary from cloud-based models
- JSON responses may require robust parsing