Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9e79b9b
Exclude tests directory from package.json files (#795)
msluszniak Feb 9, 2026
5133655
Change configuration in LLMModule so it can be set before loading mod…
msluszniak Feb 11, 2026
d6a4ece
chore!: don't resize the image segmentation output by default, change…
chmjkb Feb 11, 2026
18d7e33
Change executorch binaries (#802)
benITo47 Feb 11, 2026
22a84b7
feat!: Add time stamping to speech to text (#742)
msluszniak Feb 12, 2026
1b7363d
build: build with executorch 1.1 (#765) (#806)
IgorSwat Feb 13, 2026
8f9ca75
chore: add dedicated claude skill for RNE (#800)
mateuszlampert Feb 17, 2026
ca7d6c1
feat: add resource fetcher adapters for Expo and bare React Native
rizalibnu Jan 23, 2026
6e1e5c1
feat: add bare React Native LLM chat example app
rizalibnu Jan 23, 2026
49c0404
feat: enhance resource fetcher with error handling and new methods fo…
rizalibnu Jan 27, 2026
314fed5
chore: exclude llm_bare app from workspace
rizalibnu Jan 27, 2026
f8f48e5
feat: integrate MMKV for persistent state storage in background downl…
rizalibnu Jan 27, 2026
da04f34
chore: temporarily remove bare RN LLM example app for code review
rizalibnu Jan 27, 2026
ee1da71
chore: remove bare app directories from .gitignore
rizalibnu Jan 27, 2026
4a0f946
chore: update react-native-executorch dependency to allow any version
rizalibnu Jan 27, 2026
7352559
docs: add bare and expo adapters with installation and usage instruct…
rizalibnu Jan 27, 2026
fce6ec2
chore: add react-native-executorch as a dependency to adapters
rizalibnu Jan 27, 2026
09a8391
chore: add RNFS to the spell check wordlist
rizalibnu Jan 27, 2026
e445638
chore: update Node version in .nvmrc and adjust typecheck scripts in …
rizalibnu Jan 27, 2026
92924b4
chore: replace generic error with RnExecutorchError in ResourceFetche…
rizalibnu Jan 27, 2026
9f09e53
chore: move yarn prepare from adapter typecheck scripts to CI workflow
rizalibnu Jan 27, 2026
e6e9126
chore: update workspaces to use wildcard patterns for packages and apps
rizalibnu Jan 29, 2026
1eb8700
fix: handle directory creation errors in ResourceFetcherUtils
rizalibnu Jan 29, 2026
9cf9cbb
refactor: rename adapters to resource-fetcher packages
rizalibnu Jan 29, 2026
4020294
refactor: add resetAdapter method to ResourceFetcher
rizalibnu Jan 30, 2026
92b0009
refactor: simplify ResourceFetcherAdapter interface
rizalibnu Jan 30, 2026
7529f7d
build: configure TypeScript compilation for resource-fetcher packages
rizalibnu Jan 30, 2026
1dde669
refactor: streamline Typecheck step in CI workflow
rizalibnu Jan 30, 2026
e09abc3
refactor: update CI workflow and package scripts for improved type ch…
rizalibnu Jan 30, 2026
74ec36e
refactor: extract download completion logic and improve type safety
rizalibnu Feb 8, 2026
747307e
docs: complete JSDoc documentation for ResourceFetcher modules
rizalibnu Feb 8, 2026
38af3ed
docs: Change docs to align them with the current state of resource fe…
msluszniak Feb 16, 2026
78db189
feat!: Add time stamping to speech to text (#742)
msluszniak Feb 12, 2026
ed32d62
docs: align documentation with api reference
msluszniak Feb 17, 2026
be28882
Update functions to throw errors if adapters not initialized
msluszniak Feb 17, 2026
246348c
rebase on main tip
msluszniak Feb 17, 2026
1bd3f2c
Fix error: loading different types of models in computer vision
msluszniak Feb 18, 2026
a5440c5
Apply suggestions from code review
msluszniak Feb 18, 2026
3da1cbf
Make sure that error messages are correctly propagated
msluszniak Feb 18, 2026
aef1f76
Update packages/react-native-executorch/src/controllers/BaseOCRContro…
msluszniak Feb 18, 2026
d4da8d4
Apply suggestions from code review
msluszniak Feb 18, 2026
0d3efe9
Apply suggestions from code review
msluszniak Feb 18, 2026
9f95d60
Update docs/docs/01-fundamentals/01-getting-started.md
msluszniak Feb 18, 2026
23924b1
chore: dont default do empty string in load method
msluszniak Feb 19, 2026
f4b7578
chore: change rest of the files to pass only real path
msluszniak Feb 19, 2026
1fc3d03
chore: Create a custom error for resource fetcher adapter initialization
msluszniak Feb 19, 2026
cff408c
chore: Refactor ts code
msluszniak Feb 19, 2026
421cc64
Update README with installation instructions
msluszniak Feb 19, 2026
ac40c6f
docs: update READMEs
msluszniak Feb 19, 2026
e594d50
chore: add counting of downloads in resource fetcher
msluszniak Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .cspell-wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ torch
huggingface
bbox
bboxes
chatbots
llms
deeplab
unsqueeze
qlora
Expand Down Expand Up @@ -104,3 +106,9 @@ POTTEDPLANT
TVMONITOR
sublist
TTFT
timestamping
logprob
RNFS
pogodin
kesha
antonov
2 changes: 1 addition & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"version": "0.2",
"language": "en",
"ignorePaths": ["**/node_modules", "**/Pods"],
"ignorePaths": ["**/node_modules", "**/Pods", "**/readmes/**"],
"dictionaryDefinitions": [
{
"name": "project-words",
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
run: yarn lint

- name: Typecheck files
run: yarn typecheck
run: yarn workspaces foreach --all --topological-dev run prepare && yarn typecheck

build-library:
runs-on: ubuntu-latest
Expand All @@ -35,7 +35,5 @@ jobs:
- name: Setup
uses: ./.github/actions/setup

- name: Build package
run: |
cd packages/react-native-executorch
yarn prepare
- name: Build all packages
run: yarn workspaces foreach --all --topological-dev run prepare
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20
v22
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ React Native ExecuTorch is powering [Private Mind](https://privatemind.swmansion
```bash
# Install the package
yarn add react-native-executorch

# If you use expo, please add these packages for resource fetching:
yarn add @react-native-executorch/expo-adapter
yarn add expo-file-system expo-asset

#if you use bare React Native project use these packages:
yarn add @react-native-executorch/bare-adapter
yarn add @dr.pogodin/react-native-fs @kesha-antonov/react-native-background-downloader

# Depending on the platform, choose either iOS or Android
yarn expo run:< ios | android >
```
Expand All @@ -88,8 +97,14 @@ Add this to your component file:
import {
useLLM,
LLAMA3_2_1B,
Message
Message,
initExecutorch,
} from 'react-native-executorch';
import { ExpoResourceFetcher } from '@react-native-executorch/expo-resource-fetcher';

initExecutorch({
resourceFetcher: ExpoResourceFetcher,
});

function MyComponent() {
// Initialize the model 🚀
Expand Down
7 changes: 7 additions & 0 deletions apps/computer-vision/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Drawer } from 'expo-router/drawer';
import { initExecutorch } from 'react-native-executorch';
import { ExpoResourceFetcher } from '@react-native-executorch/expo-resource-fetcher';

import ColorPalette from '../colors';
import React, { useState } from 'react';
import { Text, StyleSheet, View } from 'react-native';
Expand All @@ -10,6 +13,10 @@ import {
} from '@react-navigation/drawer';
import { GeneratingContext } from '../context';

initExecutorch({
resourceFetcher: ExpoResourceFetcher,
});

interface CustomDrawerProps extends DrawerContentComponentProps {
isGenerating: boolean;
}
Expand Down
117 changes: 59 additions & 58 deletions apps/computer-vision/app/image_segmentation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,13 @@ import {
Skia,
AlphaType,
ColorType,
SkImage,
} from '@shopify/react-native-skia';
import { View, StyleSheet, Image } from 'react-native';
import React, { useContext, useEffect, useState } from 'react';
import { GeneratingContext } from '../../context';
import ScreenWrapper from '../../ScreenWrapper';

const width = 224;
const height = 224;

let pixels = new Uint8Array(width * height * 4);
pixels.fill(255);

let data = Skia.Data.fromBytes(pixels);
let img = Skia.Image.MakeImage(
{
width: width,
height: height,
alphaType: AlphaType.Opaque,
colorType: ColorType.RGBA_8888,
},
data,
width * 4
);

const numberToColor: number[][] = [
[255, 87, 51], // 0 Red
[51, 255, 87], // 1 Green
Expand Down Expand Up @@ -67,48 +50,58 @@ export default function ImageSegmentationScreen() {
setGlobalGenerating(model.isGenerating);
}, [model.isGenerating, setGlobalGenerating]);
const [imageUri, setImageUri] = useState('');
const [imageSize, setImageSize] = useState({ width: 0, height: 0 });
const [segImage, setSegImage] = useState<SkImage | null>(null);
const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 });

const handleCameraPress = async (isCamera: boolean) => {
const image = await getImage(isCamera);
const uri = image?.uri;
setImageUri(uri as string);
if (!image?.uri) return;
setImageUri(image.uri);
setImageSize({
width: image.width ?? 0,
height: image.height ?? 0,
});
setSegImage(null);
};

const [resultPresent, setResultPresent] = useState(false);

const runForward = async () => {
if (imageUri) {
try {
const output = await model.forward(imageUri);
pixels = new Uint8Array(width * height * 4);
if (!imageUri || imageSize.width === 0 || imageSize.height === 0) return;
try {
const { width, height } = imageSize;
const output = await model.forward(imageUri, [DeeplabLabel.ARGMAX]);
const argmax = output[DeeplabLabel.ARGMAX] || [];
const uniqueValues = new Set<number>();
for (let i = 0; i < argmax.length; i++) {
uniqueValues.add(argmax[i]);
}
const pixels = new Uint8Array(width * height * 4);

for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
for (let i = 0; i < 3; i++) {
pixels[(x * height + y) * 4 + i] =
numberToColor[
(output[DeeplabLabel.ARGMAX] || [])[x * height + y]
][i];
}
pixels[(x * height + y) * 4 + 3] = 255;
}
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
const idx = row * width + col;
const color = numberToColor[argmax[idx]] || [0, 0, 0];
pixels[idx * 4] = color[0];
pixels[idx * 4 + 1] = color[1];
pixels[idx * 4 + 2] = color[2];
pixels[idx * 4 + 3] = 255;
}

data = Skia.Data.fromBytes(pixels);
img = Skia.Image.MakeImage(
{
width: width,
height: height,
alphaType: AlphaType.Opaque,
colorType: ColorType.RGBA_8888,
},
data,
width * 4
);
setResultPresent(true);
} catch (e) {
console.error(e);
}

const data = Skia.Data.fromBytes(pixels);
const img = Skia.Image.MakeImage(
{
width,
height,
alphaType: AlphaType.Opaque,
colorType: ColorType.RGBA_8888,
},
data,
width * 4
);
setSegImage(img);
} catch (e) {
console.error(e);
}
};

Expand All @@ -135,16 +128,24 @@ export default function ImageSegmentationScreen() {
}
/>
</View>
{resultPresent && (
<View style={styles.canvasContainer}>
{segImage && (
<View
style={styles.canvasContainer}
onLayout={(e) =>
setCanvasSize({
width: e.nativeEvent.layout.width,
height: e.nativeEvent.layout.height,
})
}
>
<Canvas style={styles.canvas}>
<SkiaImage
image={img}
image={segImage}
fit="contain"
x={0}
y={0}
width={width}
height={height}
width={canvasSize.width}
height={canvasSize.height}
/>
</Canvas>
</View>
Expand Down Expand Up @@ -181,7 +182,7 @@ const styles = StyleSheet.create({
padding: 4,
},
canvas: {
width: width,
height: height,
width: '100%',
height: '100%',
},
});
5 changes: 3 additions & 2 deletions apps/computer-vision/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"lint": "eslint . --ext .ts,.tsx --fix"
},
"dependencies": {
"@react-native/metro-config": "^0.76.3",
"@react-native-executorch/expo-resource-fetcher": "workspace:*",
"@react-native/metro-config": "^0.81.5",
"@react-navigation/drawer": "^7.3.9",
"@react-navigation/native": "^7.1.6",
"@shopify/react-native-skia": "2.2.12",
Expand All @@ -21,7 +22,7 @@
"expo-linking": "~8.0.10",
"expo-router": "~6.0.17",
"expo-status-bar": "~3.0.9",
"metro-config": "^0.81.0",
"metro-config": "^0.81.5",
"react": "19.1.0",
"react-native": "0.81.5",
"react-native-device-info": "^14.0.4",
Expand Down
5 changes: 4 additions & 1 deletion apps/computer-vision/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
"customConditions": ["react-native"],
"noEmit": true,
"paths": {
"react-native-executorch": ["../../packages/react-native-executorch/src"]
"react-native-executorch": ["../../packages/react-native-executorch/src"],
"@react-native-executorch/expo-resource-fetcher": [
"../../packages/expo-resource-fetcher/src"
]
}
}
}
7 changes: 6 additions & 1 deletion apps/llm/app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { Drawer } from 'expo-router/drawer';
import { initExecutorch } from 'react-native-executorch';
import { ExpoResourceFetcher } from '@react-native-executorch/expo-resource-fetcher';
import ColorPalette from '../colors';
import React, { useState } from 'react';
import { Text, StyleSheet, View } from 'react-native';

import {
DrawerContentComponentProps,
DrawerContentScrollView,
DrawerItemList,
} from '@react-navigation/drawer';
import { GeneratingContext } from '../context';

initExecutorch({
resourceFetcher: ExpoResourceFetcher,
});

interface CustomDrawerProps extends DrawerContentComponentProps {
isGenerating: boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/llm/app/llm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function LLMScreen() {

useEffect(() => {
if (llm.error) {
console.log('LLM error:', llm.error);
console.error('LLM error:', llm.error);
}
}, [llm.error]);

Expand Down
2 changes: 1 addition & 1 deletion apps/llm/app/llm_structured_output/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function LLMScreen() {

useEffect(() => {
if (llm.error) {
console.log('LLM error:', llm.error);
console.error('LLM error:', llm.error);
}
}, [llm.error]);

Expand Down
2 changes: 1 addition & 1 deletion apps/llm/app/llm_tool_calling/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function LLMToolCallingScreen() {

useEffect(() => {
if (llm.error) {
console.log('LLM error:', llm.error);
console.error('LLM error:', llm.error);
}
}, [llm.error]);

Expand Down
Loading