gemini-nano-chrome-extension-skill
💡 摘要
该技能使开发人员能够创建利用内置AI功能的Chrome扩展,用于文本生成和翻译等任务。
🎯 适合人群
🤖 AI 吐槽: “看起来很能打,但别让配置把人劝退。”
风险:Medium。建议检查:是否发起外网请求(SSRF/数据外发);API Key/Token 的获取、存储与泄露风险。以最小权限运行,并在生产环境启用前审计代码与依赖。
name: chrome-ai-extension description: Create Chrome extensions that use built-in Chrome AI (Prompt API, Summarization, Translation, Writer). Use when building browser extensions that need AI capabilities like text generation, summarization, translation, or conversational AI features powered by Chrome's native on-device AI models.
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 request
优点
- 利用内置AI功能
- 支持多种AI功能
- 无需外部API调用
缺点
- 实验性API可能会变化
- 仅限于Chrome生态系统
- 需要特定权限
相关技能
免责声明:本内容来源于 GitHub 开源项目,仅供展示和评分分析使用。
版权归原作者所有 vibecodersph.
