react-native-nobodywho 0.1.2 → 0.3.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 CHANGED
@@ -30,13 +30,31 @@ This library uses the **GGUF format** — a binary format optimized for fast loa
30
30
  - iOS: iPhone 11 or newer with at least 4 GB of RAM.
31
31
  - Android: Snapdragon 855 / Adreno 640 / 6 GB RAM or better.
32
32
 
33
+ ## Model Loading
34
+
35
+ Models can be loaded from a local file path or downloaded automatically from HuggingFace:
36
+
37
+ ```typescript
38
+ import { Model } from "react-native-nobodywho";
39
+
40
+ // Download from HuggingFace (cached automatically)
41
+ const model = await Model.load({
42
+ modelPath: "hf://NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf",
43
+ });
44
+
45
+ // Or load from a local file
46
+ const model = await Model.load({ modelPath: "/path/to/model.gguf" });
47
+ ```
48
+
49
+ Downloaded models are cached on disk and reused on subsequent loads.
50
+
33
51
  ## Chat
34
52
 
35
53
  ```typescript
36
54
  import { Chat } from "react-native-nobodywho";
37
55
 
38
56
  const chat = await Chat.fromPath({
39
- modelPath: "/path/to/model.gguf",
57
+ modelPath: "hf://NobodyWho/Qwen_Qwen3-0.6B-GGUF/Qwen_Qwen3-0.6B-Q4_K_M.gguf",
40
58
  systemPrompt: "You are a helpful assistant.",
41
59
  });
42
60
 
@@ -42,16 +42,18 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size
42
42
 
43
43
  # NOBODYWHO_NATIVE_LIBS_DIR is passed from build.gradle via cmake arguments.
44
44
  # Fall back to src/main/jniLibs for local development where libs are placed manually.
45
+ # The .so files are pre-built shared libraries — fully linked at CI time — so the
46
+ # consumer's NDK version does not affect the Rust code.
45
47
  if(NOT NOBODYWHO_NATIVE_LIBS_DIR)
46
48
  set(NOBODYWHO_NATIVE_LIBS_DIR "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
47
49
  endif()
48
50
 
49
51
  cmake_path(
50
52
  SET MY_RUST_LIB
51
- ${NOBODYWHO_NATIVE_LIBS_DIR}/${ANDROID_ABI}/libnobodywho_uniffi.a
53
+ ${NOBODYWHO_NATIVE_LIBS_DIR}/${ANDROID_ABI}/libnobodywho_uniffi.so
52
54
  NORMALIZE
53
55
  )
54
- add_library(my_rust_lib STATIC IMPORTED)
56
+ add_library(my_rust_lib SHARED IMPORTED)
55
57
  set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB})
56
58
 
57
59
  # Add ReactAndroid libraries, being careful to account for different versions.
@@ -60,20 +60,19 @@ def packageJsonFile = file("${projectDir}/../package.json")
60
60
  def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonFile.text)
61
61
  def nobodywhoVersion = packageJson.version
62
62
 
63
- // Directory for downloaded native libraries (outside source tree to avoid Gradle conflicts)
63
+ // Directory for downloaded native shared libraries.
64
+ // These .so files are fully linked at CI time with a known-good NDK, eliminating
65
+ // NDK version coupling for consumers.
64
66
  def nativeLibsDir = new File(buildDir, "nobodywho-native")
65
67
 
66
- // Download native static libraries from GitHub Releases if not already present.
67
- // These are .a files used by CMake at link time — not .so files for jniLibs.
68
+ // Download native shared libraries from GitHub Releases if not already present.
68
69
  task resolveNativeLibraries {
69
- description = "Downloads NobodyWho native static libraries from GitHub Releases"
70
-
71
- outputs.dir(nativeLibsDir)
70
+ description = "Downloads NobodyWho native shared libraries from GitHub Releases"
72
71
 
73
72
  doLast {
74
73
  abiToTriple.each { abi, triple ->
75
74
  def abiDir = new File(nativeLibsDir, abi)
76
- def libFile = new File(abiDir, "libnobodywho_uniffi.a")
75
+ def libFile = new File(abiDir, "libnobodywho_uniffi.so")
77
76
 
78
77
  if (libFile.exists()) {
79
78
  logger.lifecycle("[NobodyWho] ${abi}: Using existing library at ${libFile.path}")
@@ -82,7 +81,7 @@ task resolveNativeLibraries {
82
81
 
83
82
  abiDir.mkdirs()
84
83
 
85
- def fileName = "libnobodywho-uniffi-${triple}-release.a"
84
+ def fileName = "libnobodywho-uniffi-${triple}-release.so"
86
85
  def downloadUrl = "https://github.com/nobodywho-ooo/nobodywho/releases/download/nobodywho-react-native-${nobodywhoVersion}/${fileName}"
87
86
 
88
87
  logger.lifecycle("[NobodyWho] ${abi}: Downloading from ${downloadUrl}")
@@ -121,7 +120,7 @@ task resolveNativeLibraries {
121
120
  } catch (Exception e) {
122
121
  throw new GradleException(
123
122
  "Failed to download NobodyWho library for ${abi}: ${e.message}\n" +
124
- "For local development, build the uniffi crate and place the .a file at: ${libFile.path}",
123
+ "For local development, build the uniffi crate and place the .so file at: ${libFile.path}",
125
124
  e
126
125
  )
127
126
  }
@@ -140,7 +139,11 @@ android {
140
139
  }
141
140
  }
142
141
 
143
- ndkVersion getExtOrDefault("ndkVersion")
142
+ // Let the consumer's rootProject.ext.ndkVersion control the NDK version.
143
+ // If not set, AGP uses the default NDK bundled with the Android SDK.
144
+ if (rootProject.ext.has("ndkVersion")) {
145
+ ndkVersion rootProject.ext.get("ndkVersion")
146
+ }
144
147
  compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
145
148
 
146
149
  defaultConfig {
@@ -160,7 +163,7 @@ android {
160
163
  }
161
164
  }
162
165
  ndk {
163
- abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
166
+ abiFilters "arm64-v8a", "x86_64"
164
167
  }
165
168
  }
166
169
 
@@ -191,6 +194,8 @@ android {
191
194
 
192
195
  sourceSets {
193
196
  main {
197
+ // Include downloaded .so files so they get packaged into the APK
198
+ jniLibs.srcDirs += [nativeLibsDir]
194
199
  if (isNewArchitectureEnabled()) {
195
200
  java.srcDirs += [
196
201
  "generated/java",
@@ -201,12 +206,12 @@ android {
201
206
  }
202
207
  }
203
208
 
204
- // Ensure native libraries are downloaded before CMake runs
205
- afterEvaluate {
206
- tasks.matching {
207
- it.name.contains("configureCMake") || it.name.contains("externalNativeBuild")
208
- }.configureEach {
209
- dependsOn(resolveNativeLibraries)
209
+ // Ensure native libraries are downloaded before CMake and JNI merge tasks run.
210
+ tasks.configureEach { task ->
211
+ if (task.name.contains("configureCMake") ||
212
+ task.name.contains("externalNativeBuild") ||
213
+ task.name.contains("ergeJniLibFolders")) {
214
+ task.dependsOn(resolveNativeLibraries)
210
215
  }
211
216
  }
212
217
 
@@ -37,6 +37,7 @@ class NobodywhoModule(reactContext: ReactApplicationContext) :
37
37
  const val NAME = "Nobodywho"
38
38
 
39
39
  init {
40
+ System.loadLibrary("nobodywho_uniffi")
40
41
  System.loadLibrary("react-native-nobodywho")
41
42
  }
42
43
  }