-
Notifications
You must be signed in to change notification settings - Fork 79
Add android skills script #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
joehan
wants to merge
11
commits into
main
Choose a base branch
from
add-android-skills-script
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
de292b8
Add script to generate Android-only skills bundle
joehan 806fb48
Exclude hosting skills from Android bundle
joehan e2c2cca
Add cleanup prompt for LLM usage
joehan 88e4e1f
Rename prompt to guide and add full process instructions
joehan ac3b28d
Update branch name in prompt and script to platform/android-studio
joehan 41ecbb0
Move transformed skills to transformations/ directory on main
joehan 6ba133b
Add README to transformations directory
joehan f538fe8
Add installation instructions to transformations README
joehan 668eac0
Merge remote-tracking branch 'origin/main' into add-android-skills-sc…
joehan 84c7b1e
Regenerate Android skills with Remote Config and cleanups
joehan b184cea
Add generated Remote Config skill for Android
joehan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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. |
46 changes: 46 additions & 0 deletions
46
transformations/android-studio/generator/generate-android-studio-bundle.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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
127
transformations/android-studio/generator/generate_android_skills.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } | ||
|
|
||
| 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); | ||
| } | ||
| } | ||
|
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(); | ||
123 changes: 123 additions & 0 deletions
123
transformations/android-studio/skills/firebase-ai-logic-basics/SKILL.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) | ||
|
|
||
|
|
||
|
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.