react-native-litert-lm 0.2.1 → 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.
Files changed (43) hide show
  1. package/README.md +331 -150
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLM.kt +140 -37
  4. package/app.plugin.js +33 -0
  5. package/cpp/HybridLiteRTLM.cpp +577 -378
  6. package/cpp/HybridLiteRTLM.hpp +66 -23
  7. package/cpp/IOSDownloadHelper.h +24 -0
  8. package/cpp/cpp-adapter.cpp +10 -2
  9. package/cpp/include/litert_lm_engine.h +502 -0
  10. package/ios/IOSDownloadHelper.mm +129 -0
  11. package/ios/LiteRTLMAutolinking.mm +30 -0
  12. package/lib/hooks.d.ts +33 -3
  13. package/lib/hooks.js +54 -23
  14. package/lib/index.d.ts +4 -1
  15. package/lib/index.js +6 -6
  16. package/lib/memoryTracker.d.ts +128 -0
  17. package/lib/memoryTracker.js +155 -0
  18. package/lib/modelFactory.d.ts +21 -2
  19. package/lib/modelFactory.js +78 -11
  20. package/lib/specs/LiteRTLM.nitro.d.ts +19 -0
  21. package/nitrogen/generated/android/LiteRTLMOnLoad.cpp +28 -18
  22. package/nitrogen/generated/android/LiteRTLMOnLoad.hpp +13 -4
  23. package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.cpp +39 -36
  24. package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.hpp +20 -22
  25. package/nitrogen/generated/android/c++/JMemoryUsage.hpp +69 -0
  26. package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLMSpec.kt +19 -18
  27. package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/MemoryUsage.kt +47 -0
  28. package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.cpp +1 -0
  29. package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.hpp +4 -0
  30. package/nitrogen/generated/shared/c++/MemoryUsage.hpp +95 -0
  31. package/package.json +12 -5
  32. package/react-native-litert-lm.podspec +20 -7
  33. package/scripts/build-ios-engine.sh +283 -0
  34. package/scripts/download-ios-frameworks.sh +72 -0
  35. package/scripts/postinstall.js +116 -0
  36. package/scripts/stubs/cxx_bridge_stubs.cc +224 -0
  37. package/scripts/stubs/gemma_model_constraint_provider.cc +46 -0
  38. package/scripts/stubs/llguidance_stubs.c +101 -0
  39. package/src/hooks.ts +107 -41
  40. package/src/index.ts +13 -6
  41. package/src/memoryTracker.ts +268 -0
  42. package/src/modelFactory.ts +107 -11
  43. package/src/specs/LiteRTLM.nitro.ts +21 -0
@@ -14,11 +14,19 @@
14
14
 
15
15
  #include "../nitrogen/generated/shared/c++/HybridLiteRTLMSpec.hpp"
16
16
 
17
- // LiteRT-LM headers (conditionally included when available via Prefab/CMake)
18
- #ifdef LITERT_LM_ENABLED
19
- #include "litert/lm/engine.h"
20
- #include "litert/lm/conversation.h"
21
- #include "litert/lm/types.h"
17
+ // LiteRT-LM C API (iOS uses prebuilt framework with C ABI)
18
+ #ifdef __APPLE__
19
+ #include "include/litert_lm_engine.h"
20
+ #endif
21
+
22
+ // Memory usage headers
23
+ #ifdef __APPLE__
24
+ #include <mach/mach.h>
25
+ #include <mach/mach_host.h>
26
+ #endif
27
+ #ifdef __ANDROID__
28
+ #include <malloc.h>
29
+ #include <fstream>
22
30
  #endif
23
31
 
24
32
  #include <string>
@@ -27,14 +35,15 @@
27
35
  #include <memory>
28
36
  #include <mutex>
29
37
  #include <functional>
38
+ #include <atomic>
30
39
 
31
40
  namespace margelo::nitro::litertlm {
32
41
 
33
42
  /**
34
43
  * HybridLiteRTLM: React Native bindings for LiteRT-LM.
35
44
  *
36
- * Wraps LiteRT-LM's Engine and Conversation classes to provide
37
- * high-level LLM inference with GPU acceleration.
45
+ * On iOS, wraps the LiteRT-LM C API (engine.h) with prebuilt framework.
46
+ * On Android, this class is unused — the Kotlin implementation is used instead.
38
47
  */
39
48
  class HybridLiteRTLM : public HybridLiteRTLMSpec {
40
49
  public:
@@ -51,24 +60,26 @@ public:
51
60
  public:
52
61
  // HybridLiteRTLMSpec interface implementation
53
62
 
54
- void loadModel(const std::string& modelPath,
63
+ std::shared_ptr<Promise<void>> loadModel(const std::string& modelPath,
55
64
  const std::optional<LLMConfig>& config) override;
56
65
 
57
- std::string sendMessage(const std::string& message) override;
66
+ std::shared_ptr<Promise<std::string>> sendMessage(const std::string& message) override;
58
67
 
59
- std::string sendMessageWithImage(const std::string& message,
68
+ std::shared_ptr<Promise<std::string>> sendMessageWithImage(const std::string& message,
60
69
  const std::string& imagePath) override;
61
70
 
62
- std::future<std::string> downloadModel(const std::string& url,
71
+ std::shared_ptr<Promise<std::string>> downloadModel(const std::string& url,
63
72
  const std::string& fileName,
64
73
  const std::optional<std::function<void(double)>>& onProgress) override;
65
74
 
66
- std::string sendMessageWithAudio(const std::string& message,
75
+ std::shared_ptr<Promise<void>> deleteModel(const std::string& fileName) override;
76
+
77
+ std::shared_ptr<Promise<std::string>> sendMessageWithAudio(const std::string& message,
67
78
  const std::string& audioPath) override;
68
79
 
69
80
  void sendMessageAsync(
70
81
  const std::string& message,
71
- const std::function<void(std::string, bool)>& onToken
82
+ const std::function<void(const std::string&, bool)>& onToken
72
83
  ) override;
73
84
 
74
85
  std::vector<Message> getHistory() override;
@@ -79,13 +90,17 @@ public:
79
90
 
80
91
  GenerationStats getStats() override;
81
92
 
93
+ MemoryUsage getMemoryUsage() override;
94
+
82
95
  void close() override;
83
96
 
84
97
  private:
85
- // LiteRT-LM resources (conditionally available on Android with Prefab)
86
- #ifdef LITERT_LM_ENABLED
87
- std::unique_ptr<litert::lm::Engine> engine_;
88
- std::unique_ptr<litert::lm::Conversation> conversation_;
98
+ // LiteRT-LM C API resources (iOS only)
99
+ #ifdef __APPLE__
100
+ LiteRtLmEngine* engine_ = nullptr;
101
+ LiteRtLmConversation* conversation_ = nullptr;
102
+ LiteRtLmConversationConfig* conv_config_ = nullptr;
103
+ LiteRtLmSessionConfig* session_config_ = nullptr;
89
104
  #endif
90
105
 
91
106
  // State
@@ -96,10 +111,11 @@ private:
96
111
  // Thread safety
97
112
  mutable std::mutex mutex_;
98
113
 
99
- // Configuration - backends
114
+ // Configuration - backend
100
115
  Backend backend_ = Backend::GPU;
101
- Backend visionBackend_ = Backend::GPU; // Gemma 3n requires GPU for vision
102
- Backend audioBackend_ = Backend::CPU; // Audio typically CPU
116
+
117
+ // System prompt / instruction
118
+ std::string systemPrompt_;
103
119
 
104
120
  // Configuration - sampling parameters
105
121
  double temperature_ = 0.7;
@@ -114,11 +130,38 @@ private:
114
130
  }
115
131
  }
116
132
 
117
- // Helper to format a message for the engine (apply chat template if needed)
118
- std::string formatUserPrompt(const std::string& message) const;
119
-
120
133
  // Helper to create a new conversation from existing engine
121
134
  void createNewConversation();
135
+
136
+ // JSON helpers for building C API message payloads
137
+ static std::string escapeJson(const std::string& input);
138
+ static std::string buildTextMessageJson(const std::string& text);
139
+ static std::string buildImageMessageJson(const std::string& text, const std::string& imagePath);
140
+ static std::string buildAudioMessageJson(const std::string& text, const std::string& audioPath);
141
+ static std::string extractTextFromResponse(const std::string& jsonResponse);
142
+
143
+ // Internal implementations (called from Promise lambdas)
144
+ void loadModelInternal(const std::string& modelPath, const std::optional<LLMConfig>& config);
145
+ std::string sendMessageInternal(const std::string& message);
146
+ std::string sendMessageWithImageInternal(const std::string& message, const std::string& imagePath);
147
+ std::string sendMessageWithAudioInternal(const std::string& message, const std::string& audioPath);
148
+
149
+ // Streaming callback context (must be a plain struct for C function pointer)
150
+ struct StreamContext {
151
+ std::function<void(const std::string&, bool)> onToken;
152
+ std::string fullResponse;
153
+ std::vector<Message>* history;
154
+ std::mutex* historyMutex;
155
+ std::string userMessage;
156
+ GenerationStats* lastStats;
157
+ std::chrono::steady_clock::time_point startTime;
158
+ int tokenCount;
159
+ };
160
+
161
+ // Static C callback for streaming (no captures needed)
162
+ static void streamCallbackFn(void* callback_data, const char* chunk,
163
+ bool is_final, const char* error_msg);
122
164
  };
123
165
 
124
166
  } // namespace margelo::nitro::litertlm
167
+
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <functional>
5
+ #include <optional>
6
+
7
+ namespace litert_lm {
8
+
9
+ /**
10
+ * Download a file from a URL to the app's Caches/litert_models directory.
11
+ * Uses NSURLSession for efficient, resumable downloads.
12
+ *
13
+ * @param url HTTPS URL to download from
14
+ * @param fileName Destination filename
15
+ * @param onProgress Optional progress callback (0.0 to 1.0)
16
+ * @return Absolute path to the downloaded file
17
+ * @throws std::runtime_error on download failure
18
+ */
19
+ std::string downloadModelFile(
20
+ const std::string& url,
21
+ const std::string& fileName,
22
+ const std::optional<std::function<void(double)>>& onProgress);
23
+
24
+ } // namespace litert_lm
@@ -2,12 +2,20 @@
2
2
  /// cpp-adapter.cpp
3
3
  /// JNI Entry Point - Required by Nitrogen to register Kotlin HybridObjects
4
4
  ///
5
+ /// Updated for react-native-nitro-modules v0.35+:
6
+ /// Uses facebook::jni::initialize() directly with registerAllNatives().
7
+ ///
5
8
 
6
9
  #include <jni.h>
10
+ #include <fbjni/fbjni.h>
7
11
  #include "LiteRTLMOnLoad.hpp"
8
12
 
9
13
  // JNI_OnLoad is called when the native library is loaded via System.loadLibrary()
10
- // This is where we initialize the Nitrogen bridge and register all Kotlin HybridObjects
14
+ // This is where we initialize the Nitrogen bridge and register all Kotlin HybridObjects.
15
+ // The new v0.35 API allows registering custom C++ native JNI classes/functions
16
+ // alongside Nitrogen's auto-generated registrations.
11
17
  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
12
- return margelo::nitro::litertlm::initialize(vm);
18
+ return facebook::jni::initialize(vm, []() {
19
+ margelo::nitro::litertlm::registerAllNatives();
20
+ });
13
21
  }