Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions transformations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Skills Transformations

This directory contains transformed versions of the skills repository, tailored for specific platforms or use cases.

## Intended Structure

Each transformation should live in its own subdirectory under `transformations/`.

```text
transformations/
├── README.md # This file
└── [transformation-name]/
├── generator/ # Scripts and guides for generation
│ ├── generate_android_skills.js
│ └── generate-android-studio-bundle.md
└── skills/ # The generated content
├── firebase-basics
└── ...
```

### Components

- **`generator/`**: Contains the scripts used to perform the transformation and any guides or prompts used to polish the output.
- **`skills/`**: Contains the actual generated skills.

## How to Install a Transformation

To install a specific transformation using the `skills` CLI, use the GitHub URL pointing to the generated skills directory:

```bash
npx skills add https://github.com/firebase/agent-skills/tree/main/transformations/[transformation-name]/skills
```

For example, to install the Android Studio bundle:

```bash
npx skills add https://github.com/firebase/agent-skills/tree/main/transformations/android-studio/skills
```

To add a new transformation, follow these steps:

1. **Create a new directory** under `transformations/` named after your platform or use case (e.g., `transformations/vscode`).
2. **Create a `generator/` directory** inside your new directory.
3. **Add your transformation script** to the `generator/` directory. This script should read from the root `skills/` directory and write to `transformations/[transformation-name]/skills/`.
4. **Add a guide or prompt** (e.g., `README.md` or `guide.md`) in the `generator/` directory explaining how to run the transformation and any manual cleanup required.
5. **Update the root documentation** if necessary to point to the new transformation.

### Best Practices

- **Automate as much as possible**: Use scripts to filter files and clean up links.
- **Use LLMs for semantic cleanup**: If regex is insufficient to fix grammar after link removal, provide a prompt for an LLM to do the final polish.
- **Keep source of truth in root `skills/`**: All transformations should be derivable from the core content in the root `skills/` directory.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generating Android Studio Skills

This guide covers the process of generating a limited version of Firebase skills for Android Studio. The generated content lives in the `transformations/android-studio/skills/` directory on the `main` branch.

## Instructions for the Operator (Human or AI)

Follow these steps to regenerate the bundle:

### 1. Run the Generation Script
Run the following command from the root of the repository:
```bash
node transformations/android-studio/generator/generate_android_skills.js
```
This will create or update the directory `transformations/android-studio/skills/` with the filtered skills.

### 2. Clean Up Content with LLM
Use the following prompt with an LLM to clean up the markdown files in `transformations/android-studio/skills/` to remove dangling references and fix grammar.

#### Prompt for LLM Cleanup
```text
You are an AI assistant helping to create a limited version of Firebase skills for Android Studio.
Your task is to clean up the provided markdown file to make it focused on Android and remove broken links or dangling text left by a filtering process.

Instructions:
1. Remove any remaining links to files that have been deleted (iOS, Web, Flutter specific files).
2. Remove lines, bullet points, or sections that are exclusively about iOS, Web, or Flutter if they are left empty or dangling after link removal.
3. Rewrite sentences that list multiple platforms to only include Android (and shared platforms like Unity if relevant), ensuring correct grammar.
4. Do NOT remove content that is generic or applicable to all platforms unless it is part of a broken list.
5. Ensure the remaining text is grammatically correct and flows naturally.

Here is the file content:
[Insert file content here]
```

Apply this to all `.md` files in `transformations/android-studio/skills/` that need cleanup (especially `SKILL.md` files).

### 3. Commit and Push
Commit the changes to your working branch and push them.
```bash
git add transformations/android-studio/skills/
git commit -m "Update Android Studio skills"
git push
```

---
Note: The script `generate_android_skills.js` and this guide live in `transformations/android-studio/generator/`. The generated content lives in `transformations/android-studio/skills/`.
127 changes: 127 additions & 0 deletions transformations/android-studio/generator/generate_android_skills.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const fs = require('fs');
const path = require('path');

const SOURCE_DIR = path.join(__dirname, '../../../skills');
const TARGET_DIR = path.join(__dirname, '../skills');

const EXCLUDED_SKILLS = [
'developing-genkit-dart',
'developing-genkit-go',
'developing-genkit-js',
'developing-genkit-python',
'xcode-project-setup',
'firebase-hosting-basics',
'firebase-app-hosting-basics'
];

const EXCLUDED_FILE_PATTERNS = [
/ios/i,
/web/i,
/flutter/i
];

function deleteFolderRecursive(directoryPath) {
if (fs.existsSync(directoryPath)) {
fs.readdirSync(directoryPath).forEach((file, index) => {
const curPath = path.join(directoryPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(directoryPath);
}
}
Comment thread
joehan marked this conversation as resolved.

function copyRecursive(src, dest) {
const exists = fs.existsSync(src);
const stats = exists && fs.statSync(src);
const isDirectory = exists && stats.isDirectory();

if (isDirectory) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest);
}
fs.readdirSync(src).forEach((childItemName) => {
copyRecursive(path.join(src, childItemName), path.join(dest, childItemName));
});
} else {
// Check if file should be excluded
const basename = path.basename(src);
const shouldExclude = EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(basename));

if (!shouldExclude) {
fs.copyFileSync(src, dest);
}
}
Comment thread
joehan marked this conversation as resolved.
}

function cleanLinks(filePath) {
if (!fs.existsSync(filePath)) return;
let content = fs.readFileSync(filePath, 'utf8');

const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;

content = content.replace(linkRegex, (match, label, href) => {
const shouldExclude = EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(href));
if (shouldExclude) {
return '';
}
return match;
});

// Clean up double commas, trailing commas in lists
content = content.replace(/,\s*,/g, ',');
content = content.replace(/,\s*or\s*,/g, ' or ');
content = content.replace(/,\s*\]/g, ']');
content = content.replace(/\[\s*,/g, '[');

// Clean up empty list items or broken sentences
content = content.replace(/Read\s*,/g, 'Read');
content = content.replace(/,\s*or\s*$/gm, '');
content = content.replace(/,\s*$/gm, '');
content = content.replace(/^\s*-\s*\*\*.*?\*\*:\s*See\s*$/gm, '');
content = content.replace(/^\s*-\s*\*\*.*?\*\*:\s*$/gm, '');
content = content.replace(/^\s*[*+-]\s*\*\*(iOS|Web|Flutter)\*\*:\s*$/gmi, '');

fs.writeFileSync(filePath, content, 'utf8');
}

function processFiles(dir) {
fs.readdirSync(dir).forEach((file) => {
const fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
processFiles(fullPath);
} else if (path.extname(fullPath) === '.md') {
cleanLinks(fullPath);
}
});
}

function main() {
console.log('Generating Android-only skills...');

// Clear target dir
deleteFolderRecursive(TARGET_DIR);
fs.mkdirSync(TARGET_DIR, { recursive: true });

// Copy skills
fs.readdirSync(SOURCE_DIR).forEach((skill) => {
if (EXCLUDED_SKILLS.includes(skill)) {
console.log(`Skipping skill: ${skill}`);
return;
}

console.log(`Copying skill: ${skill}`);
copyRecursive(path.join(SOURCE_DIR, skill), path.join(TARGET_DIR, skill));
});

// Process files to clean links
console.log('Cleaning links...');
processFiles(TARGET_DIR);

console.log('Done!');
}

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
name: firebase-ai-logic-basics
description: Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
version: 1.0.1
---

# Firebase AI Logic Basics

## Overview

Firebase AI Logic is a product of Firebase that allows developers to add gen AI to their mobile and web apps using client-side SDKs. You can call Gemini models directly from your app without managing a dedicated backend. Firebase AI Logic, which was previously known as "Vertex AI for Firebase", represents the evolution of Google's AI integration platform for mobile and web developers.

It supports the two Gemini API providers:
- **Gemini Developer API**: It has a free tier ideal for prototyping, and pay-as-you-go for production
- **Vertex AI Gemini API**: Ideal for scale with enterprise-grade production readiness, requires Blaze plan

Use the Gemini Developer API as a default, and only Vertex AI Gemini API if the application requires it.

## Setup & Initialization

### Prerequisites

- Before starting, ensure you have **Node.js 16+** and npm installed. Install them if they aren’t already available.
- Identify the platform the user is interested in building on prior to starting: Android, iOS, Flutter or Web.
- If their platform is unsupported, Direct the user to Firebase Docs to learn how to set up AI Logic for their application (share this link with the user https://firebase.google.com/docs/ai-logic/get-started)

### Installation

The library is part of the standard Firebase Web SDK.

`npm install -g firebase@latest`

If you're in a firebase directory (with a firebase.json) the currently selected project will be marked with "current" using this command:

`npx -y firebase-tools@latest projects:list`

Ensure there's at least one app associated with the current project

`npx -y firebase-tools@latest apps:list`

Initialize AI logic SDK with the init command

`npx -y firebase-tools@latest init ailogic`

This will automatically enable the Gemini Developer API in the Firebase console.

More info in [Firebase AI Logic Getting Started](https://firebase.google.com/docs/ai-logic/get-started.md.txt)

## Core Capabilities

### Text-Only Generation

### Multimodal (Text + Images/Audio/Video/PDF input)

Firebase AI Logic allows Gemini models to analyze image files directly from your app. This enables features like creating captions, answering questions about images, detecting objects, and categorizing images. Beyond images, Gemini can analyze other media types like audio, video, and PDFs by passing them as inline data with their MIME type. For files larger than 20 megabytes (which can cause HTTP 413 errors as inline data), store them in Cloud Storage for Firebase and pass their URLs to the Gemini Developer API.

### Chat Session (Multi-turn)

Maintain history automatically using `startChat`.

### Streaming Responses

To improve the user experience by showing partial results as they arrive (like a typing effect), use `generateContentStream` instead of `generateContent` for faster display of results.

### Generate Images with Nano Banana

- Start with Gemini for most use cases, and choose Imagen for specialized tasks where image quality and specific styles are critical. (Example: gemini-2.5-flash-image)
- Requires an upgraded Blaze pay-as-you-go billing plan.

### Search Grounding with the built in googleSearch tool

## Supported Platforms and Frameworks

Supported Platforms and Frameworks include Kotlin and Java for Android, Swift for iOS, JavaScript for web apps, Dart for Flutter, and C Sharp for Unity.

## Advanced Features

### Structured Output (JSON)

Enforce a specific JSON schema for the response.

### On-Device AI (Hybrid)

Hybrid on-device inference for web apps, where the Firebase Javascript SDK automatically checks for Gemini Nano's availability (after installation) and switches between on-device or cloud-hosted prompt execution. This requires specific steps to enable model usage in the Chrome browser, more info in the [hybrid-on-device-inference documentation](https://firebase.google.com/docs/ai-logic/hybrid-on-device-inference.md.txt).

## Security & Production

### App Check

> [!WARNING]
> **Critical Safety Requirement:** In order to use AI Logic safely, you MUST set up App Check on your app. This prevents unauthorized clients from using your API quota and accessing your backend resources.

See for setup instructions.

### Remote Config

Consider that you do not need to hardcode model names (e.g., `gemini-flash-lite-latest`). Use Firebase Remote Config to update model versions dynamically without deploying new client code. See [Changing model names remotely](https://firebase.google.com/docs/ai-logic/change-model-name-remotely.md.txt)


> [!WARNING]
> **CRITICAL: Backend Provisioning Required**
> For all platforms (Flutter, Android, iOS, Web), you MUST run `npx firebase-tools init ailogic` to provision the service. `flutterfire configure` ONLY handles client configuration and does NOT enable the AI service, leading to `PERMISSION_DENIED` errors.
## Initialization Code References

| Language, Framework, Platform | Gemini API provider | Context URL |
| :---- | :---- | :---- |
| Web Modular API | Gemini Developer API (Developer API) | firebase://docs/ai-logic/get-started |
| iOS (Swift) | Gemini Developer API | |
| Flutter (Dart) | Gemini Developer API | |

**Always use the most recent version of Gemini (gemini-flash-latest) unless another model is requested by the docs or the user. DO NOT USE gemini-1.5-flash. **

## References






[Android (Kotlin) SDK usage patterns](references/usage_patterns_android.md)



Loading
Loading