react-native-ai-core 0.1.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/AiCore.podspec +20 -0
- package/LICENSE +20 -0
- package/README.md +273 -0
- package/android/build.gradle +76 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/aicore/AiCoreModule.kt +328 -0
- package/android/src/main/java/com/aicore/AiCorePackage.kt +31 -0
- package/ios/AiCore.h +12 -0
- package/ios/AiCore.mm +65 -0
- package/lib/module/NativeAiCore.js +11 -0
- package/lib/module/NativeAiCore.js.map +1 -0
- package/lib/module/index.js +189 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeAiCore.d.ts +46 -0
- package/lib/typescript/src/NativeAiCore.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +123 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +164 -0
- package/src/NativeAiCore.ts +53 -0
- package/src/index.tsx +221 -0
package/AiCore.podspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "AiCore"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/albertofernandezroda/react-native-ai-core.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
|
17
|
+
s.private_header_files = "ios/**/*.h"
|
|
18
|
+
|
|
19
|
+
install_modules_dependencies(s)
|
|
20
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alberto Fernandez
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# react-native-ai-core
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/react-native-ai-core)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://developer.android.com)
|
|
6
|
+
[](https://reactnative.dev/docs/the-new-architecture/landing-page)
|
|
7
|
+
|
|
8
|
+
> **⚠️ Development in Progress** — This library is under active development. APIs may change between minor versions. Not recommended for production use yet.
|
|
9
|
+
|
|
10
|
+
On-device LLM inference for React Native using **Gemini Nano** via Google's AI Edge SDKs. Runs entirely on-device — no internet connection required, full privacy.
|
|
11
|
+
|
|
12
|
+
Supports two backends:
|
|
13
|
+
- **ML Kit AICore** (`genai-prompt`) — hardware-accelerated via the device NPU (Pixel 9+, Android 14+)
|
|
14
|
+
- **MediaPipe Tasks GenAI** — file-based inference using a local `.bin` model (any Android device with API ≥ 26)
|
|
15
|
+
|
|
16
|
+
Built with TurboModules (New Architecture), JSI bridge, zero-overhead streaming via `NativeEventEmitter`.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
| | Minimum |
|
|
23
|
+
|---|---|
|
|
24
|
+
| React Native | 0.76+ (New Architecture) |
|
|
25
|
+
| Android API | 26 (Android 8) |
|
|
26
|
+
| Kotlin | 1.9+ |
|
|
27
|
+
|
|
28
|
+
**For ML Kit AICore backend:** Pixel 9 or any device with `Feature.AI_CORE` support (Android 14+, NPU required).
|
|
29
|
+
|
|
30
|
+
**For MediaPipe backend:** Any Android device API ≥ 26. Requires a downloaded Gemini Nano `.bin` model file on the device.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
npm install react-native-ai-core
|
|
38
|
+
# or
|
|
39
|
+
yarn add react-native-ai-core
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Android setup
|
|
43
|
+
|
|
44
|
+
Add to `android/gradle.properties`:
|
|
45
|
+
|
|
46
|
+
```properties
|
|
47
|
+
minSdkVersion=26
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
No additional permissions are required. The native module is auto-linked.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import AICore from 'react-native-ai-core';
|
|
58
|
+
|
|
59
|
+
// 1. Check availability
|
|
60
|
+
const status = await AICore.checkAvailability();
|
|
61
|
+
// 'AVAILABLE' | 'AVAILABLE_NPU' | 'NEED_DOWNLOAD' | 'UNSUPPORTED'
|
|
62
|
+
|
|
63
|
+
// 2. Initialize the engine
|
|
64
|
+
// Pass an empty string '' to use the ML Kit AICore backend (Pixel 9+).
|
|
65
|
+
// Pass an absolute path to a .bin file to use the MediaPipe backend.
|
|
66
|
+
await AICore.initialize(''); // AICore native (NPU)
|
|
67
|
+
|
|
68
|
+
// 3. Generate a response
|
|
69
|
+
const answer = await AICore.generateResponse('What is React Native?');
|
|
70
|
+
console.log(answer);
|
|
71
|
+
|
|
72
|
+
// 4. Release resources when done
|
|
73
|
+
await AICore.release();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Streaming
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
const unsubscribe = AICore.generateResponseStream('Explain JSI in detail', {
|
|
80
|
+
onToken: (token, done) => {
|
|
81
|
+
process.stdout.write(token);
|
|
82
|
+
if (done) console.log('\n[stream ended]');
|
|
83
|
+
},
|
|
84
|
+
onComplete: () => console.log('Done!'),
|
|
85
|
+
onError: (err) => console.error(err.code, err.message),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Cancel subscriptions when component unmounts
|
|
89
|
+
return () => unsubscribe();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Multi-turn conversation
|
|
93
|
+
|
|
94
|
+
The native engine keeps a conversation history automatically. Each call to `generateResponse` / `generateResponseStream` includes previous turns as context.
|
|
95
|
+
|
|
96
|
+
To start a fresh conversation without releasing the model:
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
await AICore.resetConversation();
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## API Reference
|
|
105
|
+
|
|
106
|
+
### `initialize(modelPath: string): Promise<boolean>`
|
|
107
|
+
|
|
108
|
+
Initializes the inference engine.
|
|
109
|
+
|
|
110
|
+
| Argument | Type | Description |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `modelPath` | `string` | Pass `''` to use ML Kit AICore (native NPU). Pass an absolute path to a `.bin` file to use MediaPipe. |
|
|
113
|
+
|
|
114
|
+
Returns `true` on success. Throws on failure.
|
|
115
|
+
|
|
116
|
+
**Error codes:**
|
|
117
|
+
- `MODEL_NOT_FOUND` — file at `modelPath` does not exist
|
|
118
|
+
- `NPU_UNSUPPORTED` — device NPU is not compatible
|
|
119
|
+
- `INIT_FAILED` — engine failed to start
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### `generateResponse(prompt: string): Promise<string>`
|
|
124
|
+
|
|
125
|
+
Generates a complete response synchronously (waits for the full output).
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
const response = await AICore.generateResponse('Tell me a joke');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Error codes:**
|
|
132
|
+
- `NOT_INITIALIZED` — `initialize()` was not called first
|
|
133
|
+
- `GENERATION_ERROR` — model failed during inference
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### `generateResponseStream(prompt: string, callbacks: StreamCallbacks): () => void`
|
|
138
|
+
|
|
139
|
+
Generates a response token by token via streaming. Returns a cleanup function to remove event listeners.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
const StreamCallbacks = {
|
|
143
|
+
onToken: (token: string, done: boolean) => void,
|
|
144
|
+
onComplete: () => void,
|
|
145
|
+
onError: (error: AIError) => void,
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Events are delivered through `NativeEventEmitter`:
|
|
150
|
+
- `AICore_streamToken` → `{ token: string, done: boolean }`
|
|
151
|
+
- `AICore_streamComplete` → `{}`
|
|
152
|
+
- `AICore_streamError` → `{ code: string, message: string }`
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
### `checkAvailability(): Promise<AvailabilityStatus>`
|
|
157
|
+
|
|
158
|
+
Returns the current availability status of Gemini Nano on this device.
|
|
159
|
+
|
|
160
|
+
| Value | Meaning |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `'AVAILABLE'` | Model is ready to use (file-based) |
|
|
163
|
+
| `'AVAILABLE_NPU'` | Model is ready and hardware-accelerated (AICore) |
|
|
164
|
+
| `'NEED_DOWNLOAD'` | Device is compatible but model needs to be downloaded |
|
|
165
|
+
| `'UNSUPPORTED'` | Device does not meet minimum requirements |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### `release(): Promise<void>`
|
|
170
|
+
|
|
171
|
+
Releases the model from NPU/CPU memory. Call this in your cleanup effect.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
AICore.initialize('');
|
|
176
|
+
return () => { AICore.release(); };
|
|
177
|
+
}, []);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### `resetConversation(): Promise<void>`
|
|
183
|
+
|
|
184
|
+
Clears the conversation history in the native engine without releasing the model. The next call to `generateResponse` will start a new conversation.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Types
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
export type AvailabilityStatus =
|
|
192
|
+
| 'AVAILABLE'
|
|
193
|
+
| 'AVAILABLE_NPU'
|
|
194
|
+
| 'NEED_DOWNLOAD'
|
|
195
|
+
| 'UNSUPPORTED';
|
|
196
|
+
|
|
197
|
+
export interface StreamCallbacks {
|
|
198
|
+
onToken: (token: string, done: boolean) => void;
|
|
199
|
+
onComplete: () => void;
|
|
200
|
+
onError: (error: AIError) => void;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface AIError {
|
|
204
|
+
code: string;
|
|
205
|
+
message: string;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## `useAICore` Hook
|
|
212
|
+
|
|
213
|
+
A ready-to-use React hook is available in the example app as a reference implementation. It handles:
|
|
214
|
+
|
|
215
|
+
- Availability check on mount
|
|
216
|
+
- Engine lifecycle (initialize / release)
|
|
217
|
+
- Streaming with incremental message updates
|
|
218
|
+
- Conversation history reset on clear
|
|
219
|
+
- Error state management
|
|
220
|
+
|
|
221
|
+
See [`example/src/hooks/useAICore.ts`](example/src/hooks/useAICore.ts).
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Backends
|
|
226
|
+
|
|
227
|
+
### ML Kit AICore (native NPU)
|
|
228
|
+
|
|
229
|
+
Used when `modelPath = ''`. Requires a Pixel 9 or compatible device with Android's [AICore](https://developer.android.com/ml/gemini-nano) feature. The model runs fully on the device NPU with no file management needed — Google handles the model download automatically via system updates.
|
|
230
|
+
|
|
231
|
+
Dependency: `com.google.mlkit:genai-prompt:1.0.0-beta2`
|
|
232
|
+
|
|
233
|
+
### MediaPipe Tasks GenAI (file-based)
|
|
234
|
+
|
|
235
|
+
Used when `modelPath` points to a valid `.bin` file. Works on any Android device with API ≥ 26. You are responsible for placing the model file on the device (e.g., via `adb push` or a download manager).
|
|
236
|
+
|
|
237
|
+
```sh
|
|
238
|
+
adb push gemini-nano.bin /data/local/tmp/gemini-nano.bin
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Dependency: `com.google.mediapipe:tasks-genai:0.10.22`
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Roadmap
|
|
246
|
+
|
|
247
|
+
- [ ] iOS support (Core ML / Apple Neural Engine)
|
|
248
|
+
- [ ] Automatic model download manager
|
|
249
|
+
- [ ] Model quantization options
|
|
250
|
+
- [ ] System prompt / persona configuration
|
|
251
|
+
- [ ] Token count estimation
|
|
252
|
+
- [ ] Abort/cancel streaming mid-generation
|
|
253
|
+
- [ ] Web support (WebGPU / WASM)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Contributing
|
|
258
|
+
|
|
259
|
+
Contributions, issues and feature requests are welcome.
|
|
260
|
+
|
|
261
|
+
- [Development workflow](CONTRIBUTING.md#development-workflow)
|
|
262
|
+
- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
|
|
263
|
+
- [Code of conduct](CODE_OF_CONDUCT.md)
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## License
|
|
268
|
+
|
|
269
|
+
MIT © [Alberto Fernandez](https://github.com/albertofernandezroda)
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
<sub>Built with [react-native-builder-bob](https://github.com/callstack/react-native-builder-bob)</sub>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.AiCore = [
|
|
3
|
+
kotlinVersion: "2.0.21",
|
|
4
|
+
minSdkVersion: 26,
|
|
5
|
+
compileSdkVersion: 36,
|
|
6
|
+
targetSdkVersion: 36
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
ext.getExtOrDefault = { prop ->
|
|
10
|
+
if (rootProject.ext.has(prop)) {
|
|
11
|
+
return rootProject.ext.get(prop)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return AiCore[prop]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
repositories {
|
|
18
|
+
google()
|
|
19
|
+
mavenCentral()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
dependencies {
|
|
23
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
24
|
+
// noinspection DifferentKotlinGradleVersion
|
|
25
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
apply plugin: "com.android.library"
|
|
31
|
+
apply plugin: "kotlin-android"
|
|
32
|
+
|
|
33
|
+
apply plugin: "com.facebook.react"
|
|
34
|
+
|
|
35
|
+
android {
|
|
36
|
+
namespace "com.aicore"
|
|
37
|
+
|
|
38
|
+
compileSdkVersion getExtOrDefault("compileSdkVersion")
|
|
39
|
+
|
|
40
|
+
defaultConfig {
|
|
41
|
+
minSdkVersion getExtOrDefault("minSdkVersion")
|
|
42
|
+
targetSdkVersion getExtOrDefault("targetSdkVersion")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
buildFeatures {
|
|
46
|
+
buildConfig true
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
buildTypes {
|
|
50
|
+
release {
|
|
51
|
+
minifyEnabled false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
lint {
|
|
56
|
+
disable "GradleCompatible"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
compileOptions {
|
|
60
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
61
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
dependencies {
|
|
66
|
+
implementation "com.facebook.react:react-android"
|
|
67
|
+
|
|
68
|
+
// Google AI Edge — MediaPipe Tasks GenAI (modelo de archivo local)
|
|
69
|
+
implementation "com.google.mediapipe:tasks-genai:0.10.22"
|
|
70
|
+
|
|
71
|
+
// ML Kit GenAI Prompt API — accede a Gemini Nano vía AICore (Pixel 8+, sin archivo)
|
|
72
|
+
implementation "com.google.mlkit:genai-prompt:1.0.0-beta2"
|
|
73
|
+
|
|
74
|
+
// Coroutines (requerido por ML Kit Flow API)
|
|
75
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
|
|
76
|
+
}
|