capacitor-foundation-models
v7.0.0
Published
Plugin to interact with Apple's Foundation Models
Readme
Maintainers
| Maintainer | GitHub | Social | LinkedIn | | ---------------------- | ------------------------------------- | --------------------------------- | ------------------------------------------------------------------ | | Luan Freitas (ludufre) | ludufre | @ludufre | Luan Freitas |
Features
- 🤖 Apple Foundation Models: Direct integration with Apple's on-device AI models
- 🔒 Privacy-First: All processing happens on-device, no data sent to external servers
- 📱 iOS 26+ Support: Leverages the latest Apple Intelligence capabilities
- 🎯 Schema Validation: Define structured output schemas for consistent AI responses
- ⚡ Session Management: Maintain conversation context across multiple interactions
- 🌡️ Temperature Control: Fine-tune response creativity and randomness
- 📊 Availability Checking: Detect device compatibility and model availability
- 📱 Example App: A complete example app demonstrating all features
Requirements
- iOS 26.0+ (Foundation Models framework requirement)
- Apple Intelligence enabled on the device
- Compatible device (iPhone 15 Pro/Pro Max or newer, iPad with M1 or newer, Mac with Apple Silicon)
Preview (Example App)
Installation
npm install capacitor-foundation-models
npx cap syncUsage
Check Availability
First, check if Foundation Models are available on the device:
import { FoundationModels } from 'capacitor-foundation-models';
const { available, reason, capabilities } = await FoundationModels.checkAvailability();
if (available) {
console.log('Foundation Models available with capabilities:', capabilities);
} else {
console.log('Not available:', reason);
}Start a Session
Initialize a language model session with optional instructions:
await FoundationModels.startSession({
instructions: 'You are a helpful assistant that provides concise answers.'
});Simple Text Generation
Generate responses without structured output:
const result = await FoundationModels.promptWithoutSchema({
prompt: 'Explain quantum computing in simple terms',
temperature: 0.7
});
console.log(result.response);Structured Output with Schemas
Define a schema for structured responses:
// First, create a schema
await FoundationModels.createSchema({
name: 'ProductReview',
schema: {
rating: 'number',
summary: 'string',
pros: 'string',
cons: 'string',
recommended: 'boolean'
}
});
// Use the schema for structured output
const result = await FoundationModels.promptWithSchema({
prompt: 'Review this product: iPhone 15 Pro',
schema: 'ProductReview',
temperature: 0.5
});
// result.response will be a structured object matching the schema
console.log(result.response);
// {
// rating: 4.5,
// summary: "Excellent flagship phone with advanced features",
// pros: "Great camera system, powerful A17 Pro chip, premium build quality",
// cons: "Expensive, battery life could be better",
// recommended: true
// }Schema System Guide
The schema system allows you to define structured output formats for AI responses, ensuring consistent data structures that integrate seamlessly with your application logic.
Schema Types
Primitive Types
'string'- Text values'number'- Numeric values (integers or floats)'boolean'- True/false values
await FoundationModels.createSchema({
name: 'UserProfile',
schema: {
name: 'string',
age: 'number',
isActive: 'boolean'
}
});Array Types
Arrays are defined using single-element arrays containing the element type:
['string']- Array of strings['number']- Array of numbers['boolean']- Array of booleans
await FoundationModels.createSchema({
name: 'ShoppingList',
schema: {
listName: 'string',
items: ['string'], // Array of strings
prices: ['number'], // Array of numbers
purchased: ['boolean'] // Array of booleans
}
});
// Example output:
// {
// listName: "Grocery Shopping",
// items: ["Milk", "Bread", "Eggs"],
// prices: [3.99, 2.50, 4.20],
// purchased: [false, true, false]
// }Nested Objects
Objects are defined using nested structure:
await FoundationModels.createSchema({
name: 'Recipe',
schema: {
name: 'string',
servings: 'number',
ingredients: ['string'],
nutrition: { // Nested object
calories: 'number',
protein: 'number',
carbs: 'number'
}
}
});Array of Objects
Define arrays containing complex objects:
await FoundationModels.createSchema({
name: 'Quiz',
schema: {
title: 'string',
questions: [{ // Array of objects
question: 'string',
options: ['string'], // Array within object
correctAnswer: 'number',
explanation: 'string'
}]
}
});
// Example output:
// {
// title: "JavaScript Basics Quiz",
// questions: [
// {
// question: "What is a closure?",
// options: ["A function", "A variable", "A method", "A loop"],
// correctAnswer: 0,
// explanation: "A closure is a function that has access to outer scope"
// }
// ]
// }Complex Schema Examples
E-commerce Product Catalog
await FoundationModels.createSchema({
name: 'ProductCatalog',
schema: {
categoryName: 'string',
products: [{
name: 'string',
price: 'number',
inStock: 'boolean',
tags: ['string'],
specifications: {
weight: 'number',
dimensions: 'string',
warranty: 'string'
},
reviews: [{
rating: 'number',
comment: 'string',
verified: 'boolean'
}]
}]
}
});Travel Itinerary
await FoundationModels.createSchema({
name: 'TravelPlan',
schema: {
destination: 'string',
duration: 'string',
totalBudget: 'number',
days: [{
day: 'number',
activities: ['string'],
meals: [{
type: 'string', // breakfast, lunch, dinner
restaurant: 'string',
cost: 'number'
}],
transportation: ['string']
}],
tips: ['string']
}
});Schema Management
Creating Schemas
// Create a schema
await FoundationModels.createSchema({
name: 'MySchema',
schema: { /* definition */ }
});Retrieving Schemas
// Get all created schemas
const { schemas } = await FoundationModels.getSchemas();
console.log('Available schemas:', schemas);Using Schemas
// Use a schema for structured output
const result = await FoundationModels.promptWithSchema({
prompt: 'Generate content using the schema',
schema: 'MySchema',
temperature: 0.7
});Best Practices
Descriptive Names: Use clear, descriptive schema names
// Good name: 'BookReview' // Bad name: 'Schema1'Appropriate Types: Choose the right data types for your needs
schema: { price: 'number', // For calculations description: 'string', // For text content isAvailable: 'boolean' // For flags }Arrays for Lists: Use arrays when you expect multiple items
schema: { authors: ['string'], // Multiple authors chapters: [{ // Multiple chapters with details title: 'string', pages: 'number' }] }Nested Objects for Related Data: Group related properties
schema: { contact: { // Group contact information email: 'string', phone: 'string', address: 'string' } }
Error Handling
Common schema-related errors and solutions:
try {
await FoundationModels.createSchema({
name: 'TestSchema',
schema: { /* definition */ }
});
} catch (error) {
// Handle schema creation errors
if (error.message.includes('already exists')) {
console.log('Schema already exists, skipping creation');
} else if (error.message.includes('unsupported type')) {
console.log('Invalid schema type used');
}
}API Reference
checkAvailability()
checkAvailability() => Promise<AvailabilityResult>Checks if Foundation Models are available on the current device.
Returns: Promise resolving to availability status, reason if unavailable, and supported capabilities.
startSession(options?)
startSession(options?: StartSessionOptions) => Promise<void>Starts a new language model session with optional instructions.
| Param | Type | Description |
| ----- | ---- | ----------- |
| options | StartSessionOptions | Session configuration (optional) |
createSchema(options)
createSchema(options: SchemaOptions) => Promise<void>Creates a new schema for structured output generation.
| Param | Type | Description |
| ----- | ---- | ----------- |
| options | SchemaOptions | Schema definition with name and structure |
getSchemas()
getSchemas() => Promise<{ schemas: SchemaOptions[] }>Retrieves all available schemas that have been created in the current session.
Returns: Promise resolving to an object containing an array of all created schemas.
promptWithoutSchema(options)
promptWithoutSchema(options: PromptWithoutSchemaOptions) => Promise<PromptResult>Generates a text response without structured output constraints.
| Param | Type | Description |
| ----- | ---- | ----------- |
| options | PromptWithoutSchemaOptions | Prompt text and generation options |
promptWithSchema(options)
promptWithSchema(options: PromptWithSchemaOptions) => Promise<PromptResult>Generates a structured response based on a predefined schema.
| Param | Type | Description |
| ----- | ---- | ----------- |
| options | PromptWithSchemaOptions | Prompt text, schema name, and generation options |
Type Definitions
AvailabilityResult
| Property | Type | Description |
| -------- | ---- | ----------- |
| available | boolean | Whether Foundation Models are available |
| reason | string | Reason if not available (optional) |
| capabilities | string[] | Available language capabilities (optional) |
StartSessionOptions
| Property | Type | Description |
| -------- | ---- | ----------- |
| instructions | string | System instructions for the model (optional) |
PromptWithoutSchemaOptions
| Property | Type | Description |
| -------- | ---- | ----------- |
| prompt | string | The input prompt text |
| temperature | number | Controls randomness (0.0-2.0, default: 1.0) |
PromptWithSchemaOptions
| Property | Type | Description |
| -------- | ---- | ----------- |
| prompt | string | The input prompt text |
| schema | string | Name of the schema to use |
| temperature | number | Controls randomness (0.0-2.0, default: 1.0) |
SchemaOptions
| Property | Type | Description |
| -------- | ---- | ----------- |
| name | string | Unique name for the schema |
| schema | Record<string, SchemaValue> | Schema definition object |
SchemaValue
Supported schema types:
- Primitive Types:
'string','number','boolean' - Array Types:
['string'],['number'],['boolean'],[object] - Nested Objects:
{ [key: string]: SchemaValue }
The SchemaValue type is recursive, allowing for complex nested structures combining all supported types.
Error Handling
The plugin provides detailed error messages for various scenarios:
try {
await FoundationModels.promptWithoutSchema({
prompt: 'Hello',
temperature: 0.5
});
} catch (error) {
console.error('Error:', error.message);
// Possible errors:
// - "Language model session has not been started. Call startSession() first."
// - "Invalid temperature value: 3.0. Must be between 0.0 and 2.0"
// - "Prompt cannot be empty"
// - "Language model is unavailable: [reason]"
}Platform Support
| Platform | Support | Notes | | -------- | ------- | ----- | | iOS | ✅ iOS 26.0+ | Requires Apple Intelligence enabled | | Android | ❌ | Foundation Models is Apple-exclusive | | Web | ❌ | Foundation Models requires native iOS |
Example App
Check out the example app for a complete implementation example showing:
- Availability checking
- Session management
- Schema creation and usage
- Error handling
- Temperature control
Troubleshooting
"Foundation Models are not available"
- Ensure you're running iOS 26.0 or later
- Verify Apple Intelligence is enabled in Settings
- Check that your device supports Apple Intelligence
- Confirm you're testing on a physical device, not simulator
"Session not started" errors
- Always call
startSession()before making prompt requests - Handle session initialization errors appropriately
Schema-related errors
- Ensure schema names are unique and not empty
- Verify schema structure matches supported types
- Create schemas before using them in prompts
Contributing
Contributions are welcome! Please feel free to submit pull requests or open issues.
License
This project is licensed under the MIT License.
Author
Luan Freitas - @ludufre
Acknowledgments
- Built with Capacitor
- Powered by Apple's Foundation Models framework
- Designed for privacy-first AI interactions
