apple-intelligence-example 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/capacitor.config.ts +9 -0
- package/package.json +19 -0
- package/www/index.html +296 -0
- package/www/js/app.js +280 -0
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Apple Intelligence Plugin - Example App
|
|
2
|
+
|
|
3
|
+
This is a minimal Capacitor app that demonstrates how to use the `capacitor-apple-intelligence` plugin.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- **iOS 26+** (required for Apple Intelligence APIs)
|
|
8
|
+
- **Xcode** (latest version recommended)
|
|
9
|
+
- **Node.js** and **npm**
|
|
10
|
+
- An iOS device or simulator running iOS 26+
|
|
11
|
+
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
1. **Install dependencies:**
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
2. **Add iOS platform:**
|
|
20
|
+
```bash
|
|
21
|
+
npm run add:ios
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
3. **Sync Capacitor:**
|
|
25
|
+
```bash
|
|
26
|
+
npm run sync
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
4. **Open in Xcode:**
|
|
30
|
+
```bash
|
|
31
|
+
npm run open:ios
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
5. **Build and Run:**
|
|
35
|
+
- Select your target device/simulator in Xcode
|
|
36
|
+
- Click the Run button (or press Cmd+R)
|
|
37
|
+
- The app should launch on your device
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
The example app provides a simple interface to test all three plugin methods:
|
|
42
|
+
|
|
43
|
+
### 1. Generate JSON
|
|
44
|
+
- **Method:** `generateJSON()`
|
|
45
|
+
- **Input:** Prompt + JSON Schema
|
|
46
|
+
- **Output:** Structured JSON data matching the schema
|
|
47
|
+
- **Example:** Generate a user profile with name, age, and occupation
|
|
48
|
+
|
|
49
|
+
### 2. Generate Text
|
|
50
|
+
- **Method:** `generateText()`
|
|
51
|
+
- **Input:** Prompt only
|
|
52
|
+
- **Output:** Plain text response
|
|
53
|
+
- **Example:** Generate a creative story or description
|
|
54
|
+
|
|
55
|
+
### 3. Generate Text with Language
|
|
56
|
+
- **Method:** `generateTextWithLanguage()`
|
|
57
|
+
- **Input:** Prompt + Target Language
|
|
58
|
+
- **Output:** Plain text in the specified language
|
|
59
|
+
- **Example:** Generate text in Spanish, French, German, etc.
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
1. Enter a prompt in the text field
|
|
64
|
+
2. For JSON generation, modify the schema if needed
|
|
65
|
+
3. For language-specific generation, select your target language
|
|
66
|
+
4. Click the appropriate button to test the method
|
|
67
|
+
5. View the results in the output section below
|
|
68
|
+
|
|
69
|
+
## Troubleshooting
|
|
70
|
+
|
|
71
|
+
### Plugin not found
|
|
72
|
+
- Make sure you ran `npm install` in the example directory
|
|
73
|
+
- Verify the parent plugin is built: `cd .. && npm run build`
|
|
74
|
+
- Re-sync Capacitor: `npm run sync`
|
|
75
|
+
|
|
76
|
+
### iOS 26+ requirement
|
|
77
|
+
- The Apple Intelligence APIs require iOS 26 or later
|
|
78
|
+
- Check your simulator/device iOS version
|
|
79
|
+
- Update to the latest iOS beta if needed
|
|
80
|
+
|
|
81
|
+
### Build errors in Xcode
|
|
82
|
+
- Clean build folder: Product → Clean Build Folder
|
|
83
|
+
- Delete derived data
|
|
84
|
+
- Ensure you have the latest Xcode version
|
|
85
|
+
|
|
86
|
+
## Project Structure
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
example/
|
|
90
|
+
├── www/
|
|
91
|
+
│ ├── index.html # Main UI
|
|
92
|
+
│ └── js/
|
|
93
|
+
│ └── app.js # Plugin integration logic
|
|
94
|
+
├── capacitor.config.ts # Capacitor configuration
|
|
95
|
+
├── package.json # Dependencies
|
|
96
|
+
└── README.md # This file
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Learn More
|
|
100
|
+
|
|
101
|
+
- [Plugin Documentation](../README.md)
|
|
102
|
+
- [Capacitor Documentation](https://capacitorjs.com/docs)
|
|
103
|
+
- [Apple Intelligence APIs](https://developer.apple.com/documentation/foundation/foundationmodels)
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "apple-intelligence-example",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Example app for testing Capacitor Apple Intelligence plugin",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "echo 'No build step needed for static HTML'",
|
|
7
|
+
"open:ios": "npx cap open ios",
|
|
8
|
+
"sync": "npx cap sync",
|
|
9
|
+
"add:ios": "npx cap add ios"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@capacitor/core": "^8.0.0",
|
|
13
|
+
"capacitor-apple-intelligence": "file:.."
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@capacitor/cli": "^8.0.0",
|
|
17
|
+
"@capacitor/ios": "^8.0.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
package/www/index.html
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Apple Intelligence Example</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
body {
|
|
16
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
17
|
+
background: #f5f5f5;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
padding: 20px;
|
|
20
|
+
color: #333;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.container {
|
|
24
|
+
max-width: 800px;
|
|
25
|
+
margin: 0 auto;
|
|
26
|
+
background: white;
|
|
27
|
+
border-radius: 20px;
|
|
28
|
+
padding: 30px;
|
|
29
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
h1 {
|
|
33
|
+
color: #333;
|
|
34
|
+
margin-bottom: 5px;
|
|
35
|
+
font-size: 28px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.subtitle {
|
|
39
|
+
color: #666;
|
|
40
|
+
margin-bottom: 10px;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.status-badge {
|
|
45
|
+
display: inline-block;
|
|
46
|
+
padding: 6px 12px;
|
|
47
|
+
border-radius: 6px;
|
|
48
|
+
font-size: 12px;
|
|
49
|
+
font-weight: 600;
|
|
50
|
+
margin-bottom: 20px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.status-available {
|
|
54
|
+
background: #d4edda;
|
|
55
|
+
color: #155724;
|
|
56
|
+
border: 1px solid #c3e6cb;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.status-unavailable {
|
|
60
|
+
background: #f8d7da;
|
|
61
|
+
color: #721c24;
|
|
62
|
+
border: 1px solid #f5c6cb;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.section {
|
|
66
|
+
margin-bottom: 25px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
label {
|
|
70
|
+
display: block;
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
margin-bottom: 8px;
|
|
73
|
+
color: #444;
|
|
74
|
+
font-size: 14px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
input[type="text"],
|
|
78
|
+
textarea,
|
|
79
|
+
select {
|
|
80
|
+
width: 100%;
|
|
81
|
+
padding: 12px;
|
|
82
|
+
border: 2px solid #e0e0e0;
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
font-size: 14px;
|
|
85
|
+
font-family: inherit;
|
|
86
|
+
transition: border-color 0.3s;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
input[type="text"]:focus,
|
|
90
|
+
textarea:focus,
|
|
91
|
+
select:focus {
|
|
92
|
+
outline: none;
|
|
93
|
+
border-color: #667eea;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
textarea {
|
|
97
|
+
resize: vertical;
|
|
98
|
+
min-height: 100px;
|
|
99
|
+
font-family: 'Courier New', monospace;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.button-group {
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
105
|
+
gap: 10px;
|
|
106
|
+
margin-top: 20px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
button {
|
|
110
|
+
padding: 14px 24px;
|
|
111
|
+
background: #007aff;
|
|
112
|
+
color: white;
|
|
113
|
+
border: none;
|
|
114
|
+
border-radius: 8px;
|
|
115
|
+
font-size: 14px;
|
|
116
|
+
font-weight: 600;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
transition: background 0.2s;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
button:hover {
|
|
122
|
+
background: #0051d5;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
button:active {
|
|
126
|
+
background: #004bb5;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
button:disabled {
|
|
130
|
+
opacity: 0.5;
|
|
131
|
+
cursor: not-allowed;
|
|
132
|
+
background: #007aff;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.output {
|
|
136
|
+
margin-top: 30px;
|
|
137
|
+
padding: 20px;
|
|
138
|
+
background: #f8f9fa;
|
|
139
|
+
border-radius: 8px;
|
|
140
|
+
border-left: 4px solid #007aff;
|
|
141
|
+
min-height: 100px;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.output h3 {
|
|
145
|
+
margin-bottom: 10px;
|
|
146
|
+
color: #007aff;
|
|
147
|
+
font-size: 16px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.output pre {
|
|
151
|
+
background: white;
|
|
152
|
+
padding: 15px;
|
|
153
|
+
border-radius: 6px;
|
|
154
|
+
overflow-x: auto;
|
|
155
|
+
font-size: 13px;
|
|
156
|
+
line-height: 1.5;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.error {
|
|
160
|
+
border-left-color: #e74c3c;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.error h3 {
|
|
164
|
+
color: #e74c3c;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.loading {
|
|
168
|
+
display: inline-block;
|
|
169
|
+
width: 16px;
|
|
170
|
+
height: 16px;
|
|
171
|
+
border: 3px solid rgba(255, 255, 255, 0.3);
|
|
172
|
+
border-radius: 50%;
|
|
173
|
+
border-top-color: white;
|
|
174
|
+
animation: spin 1s linear infinite;
|
|
175
|
+
margin-left: 8px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@keyframes spin {
|
|
179
|
+
to {
|
|
180
|
+
transform: rotate(360deg);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.info-box {
|
|
185
|
+
background: #e3f2fd;
|
|
186
|
+
padding: 15px;
|
|
187
|
+
border-radius: 8px;
|
|
188
|
+
margin-bottom: 20px;
|
|
189
|
+
border-left: 4px solid #2196f3;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.info-box p {
|
|
193
|
+
margin: 5px 0;
|
|
194
|
+
font-size: 13px;
|
|
195
|
+
color: #1565c0;
|
|
196
|
+
}
|
|
197
|
+
</style>
|
|
198
|
+
</head>
|
|
199
|
+
|
|
200
|
+
<body>
|
|
201
|
+
<div class="container">
|
|
202
|
+
<h1>🧠 Apple Intelligence Plugin</h1>
|
|
203
|
+
<p class="subtitle">Test the Capacitor Apple Intelligence plugin methods</p>
|
|
204
|
+
<div id="status-badge" class="status-badge status-unavailable">Checking availability...</div>
|
|
205
|
+
|
|
206
|
+
<div class="info-box">
|
|
207
|
+
<p><strong>Requirements:</strong> iOS 26+ device or simulator</p>
|
|
208
|
+
<p><strong>Note:</strong> This plugin uses on-device Apple Intelligence APIs</p>
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div class="section">
|
|
212
|
+
<label for="prompt">Prompt</label>
|
|
213
|
+
<input type="text" id="prompt" placeholder="Enter your prompt here..."
|
|
214
|
+
value="Generate a user profile with name, age, and occupation">
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div class="section">
|
|
218
|
+
<label for="schema">JSON Schema (for generateJSON)</label>
|
|
219
|
+
<textarea id="schema" placeholder='{"type": "object", "properties": {...}}'>{
|
|
220
|
+
"type": "object",
|
|
221
|
+
"properties": {
|
|
222
|
+
"name": { "type": "string" },
|
|
223
|
+
"age": { "type": "number" },
|
|
224
|
+
"occupation": { "type": "string" }
|
|
225
|
+
},
|
|
226
|
+
"required": ["name", "age", "occupation"]
|
|
227
|
+
}</textarea>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<div class="section">
|
|
231
|
+
<label for="language">Target Language (for generateTextWithLanguage)</label>
|
|
232
|
+
<select id="language">
|
|
233
|
+
<option value="en">English</option>
|
|
234
|
+
<option value="es">Spanish</option>
|
|
235
|
+
<option value="fr">French</option>
|
|
236
|
+
<option value="de">German</option>
|
|
237
|
+
<option value="ja">Japanese</option>
|
|
238
|
+
<option value="zh">Chinese</option>
|
|
239
|
+
</select>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<div class="section">
|
|
243
|
+
<label for="imageStyle">Image Style (for generateImage)</label>
|
|
244
|
+
<select id="imageStyle">
|
|
245
|
+
<option value="animation">Animation (Default)</option>
|
|
246
|
+
<option value="illustration">Illustration</option>
|
|
247
|
+
<option value="sketch">Sketch</option>
|
|
248
|
+
</select>
|
|
249
|
+
<p class="info-text" style="margin-top: 6px; font-size: 12px; color: #666;">
|
|
250
|
+
Note: Apple's on-device Image Playground only supports these 3 styles.
|
|
251
|
+
</p>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<div class="section">
|
|
255
|
+
<label for="sourceImage">Source Image (Optional - for face-based generation)</label>
|
|
256
|
+
<input type="file" id="sourceImage" accept="image/*" onchange="previewSourceImage(event)"
|
|
257
|
+
style="padding: 8px; background: #f8f9fa;">
|
|
258
|
+
<p class="info-text" style="margin-top: 6px; font-size: 12px; color: #666;">
|
|
259
|
+
Required when generating images of people. Select a photo with a visible face.
|
|
260
|
+
</p>
|
|
261
|
+
<div id="sourceImagePreview" style="margin-top: 10px; display: none;">
|
|
262
|
+
<img id="sourceImagePreviewImg"
|
|
263
|
+
style="max-width: 150px; max-height: 150px; border-radius: 8px; border: 2px solid #e0e0e0;">
|
|
264
|
+
<button onclick="clearSourceImage()"
|
|
265
|
+
style="display: block; margin-top: 8px; padding: 6px 12px; font-size: 12px; background: #dc3545;">
|
|
266
|
+
✕ Clear Image
|
|
267
|
+
</button>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<div class="button-group">
|
|
272
|
+
<button onclick="testGenerateJSON()">
|
|
273
|
+
📋 Generate JSON
|
|
274
|
+
</button>
|
|
275
|
+
<button onclick="testGenerateText()">
|
|
276
|
+
📝 Generate Text
|
|
277
|
+
</button>
|
|
278
|
+
<button onclick="testGenerateTextWithLanguage()">
|
|
279
|
+
🌍 Generate Text (Language)
|
|
280
|
+
</button>
|
|
281
|
+
<button onclick="testGenerateImage()">
|
|
282
|
+
🎨 Generate Image
|
|
283
|
+
</button>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<div id="output" class="output" style="display: none;">
|
|
287
|
+
<h3>Result</h3>
|
|
288
|
+
<pre id="result"></pre>
|
|
289
|
+
<div id="imageResult" style="margin-top: 15px; display: none;"></div>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
<script src="js/app.js"></script>
|
|
294
|
+
</body>
|
|
295
|
+
|
|
296
|
+
</html>
|
package/www/js/app.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// Access the plugin through Capacitor's Plugins API
|
|
2
|
+
const { AppleIntelligence } = Capacitor.Plugins;
|
|
3
|
+
|
|
4
|
+
// Helper function to display results
|
|
5
|
+
function displayResult(result, isError = false) {
|
|
6
|
+
const outputDiv = document.getElementById('output');
|
|
7
|
+
const resultPre = document.getElementById('result');
|
|
8
|
+
|
|
9
|
+
outputDiv.style.display = 'block';
|
|
10
|
+
outputDiv.className = isError ? 'output error' : 'output';
|
|
11
|
+
|
|
12
|
+
if (isError) {
|
|
13
|
+
resultPre.textContent = `Error: ${result}`;
|
|
14
|
+
} else {
|
|
15
|
+
resultPre.textContent = JSON.stringify(result, null, 2);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Helper function to get input values
|
|
20
|
+
function getInputs() {
|
|
21
|
+
return {
|
|
22
|
+
prompt: document.getElementById('prompt').value,
|
|
23
|
+
schema: document.getElementById('schema').value,
|
|
24
|
+
language: document.getElementById('language').value,
|
|
25
|
+
imageStyle: document.getElementById('imageStyle').value,
|
|
26
|
+
sourceImageBase64: window.selectedSourceImageBase64 || null
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Store selected source image as base64
|
|
31
|
+
window.selectedSourceImageBase64 = null;
|
|
32
|
+
|
|
33
|
+
// Preview source image when selected
|
|
34
|
+
function previewSourceImage(event) {
|
|
35
|
+
const file = event.target.files[0];
|
|
36
|
+
if (!file) return;
|
|
37
|
+
|
|
38
|
+
const reader = new FileReader();
|
|
39
|
+
reader.onload = function (e) {
|
|
40
|
+
const base64Full = e.target.result;
|
|
41
|
+
// Extract just the base64 data (remove data:image/...;base64, prefix)
|
|
42
|
+
const base64Data = base64Full.split(',')[1];
|
|
43
|
+
window.selectedSourceImageBase64 = base64Data;
|
|
44
|
+
|
|
45
|
+
// Show preview
|
|
46
|
+
const preview = document.getElementById('sourceImagePreview');
|
|
47
|
+
const previewImg = document.getElementById('sourceImagePreviewImg');
|
|
48
|
+
previewImg.src = base64Full;
|
|
49
|
+
preview.style.display = 'block';
|
|
50
|
+
};
|
|
51
|
+
reader.readAsDataURL(file);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Clear source image
|
|
55
|
+
function clearSourceImage() {
|
|
56
|
+
window.selectedSourceImageBase64 = null;
|
|
57
|
+
document.getElementById('sourceImage').value = '';
|
|
58
|
+
document.getElementById('sourceImagePreview').style.display = 'none';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Helper function to disable/enable buttons
|
|
62
|
+
function setButtonsDisabled(disabled) {
|
|
63
|
+
const buttons = document.querySelectorAll('button');
|
|
64
|
+
buttons.forEach(button => button.disabled = disabled);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Test generateJSON method
|
|
68
|
+
async function testGenerateJSON() {
|
|
69
|
+
const { prompt, schema } = getInputs();
|
|
70
|
+
|
|
71
|
+
if (!prompt || !schema) {
|
|
72
|
+
displayResult('Please enter both a prompt and a schema', true);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
setButtonsDisabled(true);
|
|
78
|
+
displayResult('Generating JSON...', false);
|
|
79
|
+
|
|
80
|
+
// Parse the schema to validate it
|
|
81
|
+
let parsedSchema;
|
|
82
|
+
try {
|
|
83
|
+
parsedSchema = JSON.parse(schema);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
throw new Error('Invalid JSON schema: ' + e.message);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const result = await AppleIntelligence.generate({
|
|
89
|
+
messages: [
|
|
90
|
+
{ role: 'user', content: prompt }
|
|
91
|
+
],
|
|
92
|
+
response_format: {
|
|
93
|
+
type: 'json_schema',
|
|
94
|
+
schema: parsedSchema
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (result.success) {
|
|
99
|
+
displayResult({
|
|
100
|
+
method: 'generate',
|
|
101
|
+
prompt: prompt,
|
|
102
|
+
schema: parsedSchema,
|
|
103
|
+
result: result.data
|
|
104
|
+
}, false);
|
|
105
|
+
} else {
|
|
106
|
+
throw new Error(result.error?.message || 'Generation failed');
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
displayResult(error.message || error.toString(), true);
|
|
110
|
+
} finally {
|
|
111
|
+
setButtonsDisabled(false);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Test generateText method
|
|
116
|
+
async function testGenerateText() {
|
|
117
|
+
const { prompt } = getInputs();
|
|
118
|
+
|
|
119
|
+
if (!prompt) {
|
|
120
|
+
displayResult('Please enter a prompt', true);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
setButtonsDisabled(true);
|
|
126
|
+
displayResult('Generating text...', false);
|
|
127
|
+
|
|
128
|
+
const result = await AppleIntelligence.generateText({
|
|
129
|
+
messages: [
|
|
130
|
+
{ role: 'user', content: prompt }
|
|
131
|
+
]
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (result.success) {
|
|
135
|
+
displayResult({
|
|
136
|
+
method: 'generateText',
|
|
137
|
+
prompt: prompt,
|
|
138
|
+
result: result.content
|
|
139
|
+
}, false);
|
|
140
|
+
} else {
|
|
141
|
+
throw new Error(result.error?.message || 'Generation failed');
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
displayResult(error.message || error.toString(), true);
|
|
145
|
+
} finally {
|
|
146
|
+
setButtonsDisabled(false);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Test generateTextWithLanguage method
|
|
151
|
+
async function testGenerateTextWithLanguage() {
|
|
152
|
+
const { prompt, language } = getInputs();
|
|
153
|
+
|
|
154
|
+
if (!prompt) {
|
|
155
|
+
displayResult('Please enter a prompt', true);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
setButtonsDisabled(true);
|
|
161
|
+
displayResult(`Generating text in ${language}...`, false);
|
|
162
|
+
|
|
163
|
+
const result = await AppleIntelligence.generateTextWithLanguage({
|
|
164
|
+
messages: [
|
|
165
|
+
{ role: 'user', content: prompt }
|
|
166
|
+
],
|
|
167
|
+
language: language
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (result.success) {
|
|
171
|
+
displayResult({
|
|
172
|
+
method: 'generateTextWithLanguage',
|
|
173
|
+
prompt: prompt,
|
|
174
|
+
language: language,
|
|
175
|
+
result: result.content
|
|
176
|
+
}, false);
|
|
177
|
+
} else {
|
|
178
|
+
throw new Error(result.error?.message || 'Generation failed');
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
displayResult(error.message || error.toString(), true);
|
|
182
|
+
} finally {
|
|
183
|
+
setButtonsDisabled(false);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Test generateImage method
|
|
188
|
+
async function testGenerateImage() {
|
|
189
|
+
const { prompt, imageStyle, sourceImageBase64 } = getInputs();
|
|
190
|
+
|
|
191
|
+
if (!prompt) {
|
|
192
|
+
displayResult('Please enter a prompt', true);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Clear previous images
|
|
197
|
+
const imageResultDiv = document.getElementById('imageResult');
|
|
198
|
+
imageResultDiv.innerHTML = '';
|
|
199
|
+
imageResultDiv.style.display = 'none';
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
setButtonsDisabled(true);
|
|
203
|
+
const statusMsg = sourceImageBase64
|
|
204
|
+
? 'Generating image with source face...'
|
|
205
|
+
: 'Generating image...';
|
|
206
|
+
displayResult(statusMsg, false);
|
|
207
|
+
|
|
208
|
+
const request = {
|
|
209
|
+
prompt: prompt,
|
|
210
|
+
style: imageStyle || undefined,
|
|
211
|
+
count: 1
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Add source image if provided
|
|
215
|
+
if (sourceImageBase64) {
|
|
216
|
+
request.sourceImage = sourceImageBase64;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const result = await AppleIntelligence.generateImage(request);
|
|
220
|
+
|
|
221
|
+
if (result.success && result.images) {
|
|
222
|
+
displayResult({
|
|
223
|
+
method: 'generateImage',
|
|
224
|
+
prompt: prompt,
|
|
225
|
+
style: imageStyle,
|
|
226
|
+
hasSourceImage: !!sourceImageBase64,
|
|
227
|
+
imageCount: result.images.length
|
|
228
|
+
}, false);
|
|
229
|
+
|
|
230
|
+
// Display images
|
|
231
|
+
imageResultDiv.style.display = 'block';
|
|
232
|
+
result.images.forEach(base64 => {
|
|
233
|
+
const img = document.createElement('img');
|
|
234
|
+
img.src = `data:image/jpeg;base64,${base64}`;
|
|
235
|
+
img.style.maxWidth = '100%';
|
|
236
|
+
img.style.borderRadius = '8px';
|
|
237
|
+
img.style.marginTop = '10px';
|
|
238
|
+
img.style.border = '1px solid #ddd';
|
|
239
|
+
imageResultDiv.appendChild(img);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
} else {
|
|
243
|
+
throw new Error(result.error?.message || 'Generation failed');
|
|
244
|
+
}
|
|
245
|
+
} catch (error) {
|
|
246
|
+
displayResult(error.message || error.toString(), true);
|
|
247
|
+
} finally {
|
|
248
|
+
setButtonsDisabled(false);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// Display ready message on load
|
|
255
|
+
document.addEventListener('DOMContentLoaded', async () => {
|
|
256
|
+
console.log('Apple Intelligence Example App loaded');
|
|
257
|
+
console.log('Plugin available:', typeof AppleIntelligence !== 'undefined');
|
|
258
|
+
|
|
259
|
+
// Check Apple Intelligence availability
|
|
260
|
+
const statusBadge = document.getElementById('status-badge');
|
|
261
|
+
try {
|
|
262
|
+
const result = await AppleIntelligence.checkAvailability();
|
|
263
|
+
console.log('Availability result:', result);
|
|
264
|
+
|
|
265
|
+
if (result && result.available) {
|
|
266
|
+
statusBadge.textContent = '✓ Apple Intelligence Available';
|
|
267
|
+
statusBadge.className = 'status-badge status-available';
|
|
268
|
+
} else {
|
|
269
|
+
statusBadge.textContent = '✗ Apple Intelligence Unavailable';
|
|
270
|
+
statusBadge.className = 'status-badge status-unavailable';
|
|
271
|
+
if (result && result.error) {
|
|
272
|
+
console.log('Availability error:', result.error);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
} catch (error) {
|
|
276
|
+
statusBadge.textContent = '✗ Apple Intelligence Unavailable';
|
|
277
|
+
statusBadge.className = 'status-badge status-unavailable';
|
|
278
|
+
console.error('Availability check failed:', error);
|
|
279
|
+
}
|
|
280
|
+
});
|