@dr33m/react-native-litert-lm 0.5.1 → 0.5.3

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 (35) hide show
  1. package/android/src/main/java/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLM.kt +41 -8
  2. package/app.plugin.js +20 -1
  3. package/ios/HybridLiteRTLM.swift +7 -0
  4. package/lib/index.d.ts +1 -1
  5. package/lib/specs/LiteRTLM.nitro.d.ts +15 -0
  6. package/nitrogen/generated/android/c++/JBackend.hpp +1 -1
  7. package/nitrogen/generated/android/c++/JExecuteResult.hpp +1 -1
  8. package/nitrogen/generated/android/c++/JGenerationStats.hpp +1 -1
  9. package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.cpp +9 -0
  10. package/nitrogen/generated/android/c++/JHybridLiteRTLMSpec.hpp +1 -0
  11. package/nitrogen/generated/android/c++/JLLMConfig.hpp +1 -1
  12. package/nitrogen/generated/android/c++/JMemoryUsage.hpp +1 -1
  13. package/nitrogen/generated/android/c++/JMessage.hpp +1 -1
  14. package/nitrogen/generated/android/c++/JModelCapabilities.hpp +57 -0
  15. package/nitrogen/generated/android/c++/JModelFile.hpp +1 -1
  16. package/nitrogen/generated/android/c++/JMultimodalPart.hpp +1 -1
  17. package/nitrogen/generated/android/c++/JPartType.hpp +1 -1
  18. package/nitrogen/generated/android/c++/JRole.hpp +1 -1
  19. package/nitrogen/generated/android/c++/JToolCall.hpp +1 -1
  20. package/nitrogen/generated/android/c++/JToolDefinition.hpp +1 -1
  21. package/nitrogen/generated/android/c++/JToolResponse.hpp +1 -1
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/HybridLiteRTLMSpec.kt +4 -0
  23. package/nitrogen/generated/android/kotlin/com/margelo/nitro/dev/litert/litertlm/ModelCapabilities.kt +51 -0
  24. package/nitrogen/generated/ios/LiteRTLM-Swift-Cxx-Bridge.hpp +12 -0
  25. package/nitrogen/generated/ios/LiteRTLM-Swift-Cxx-Umbrella.hpp +3 -0
  26. package/nitrogen/generated/ios/c++/HybridLiteRTLMSpecSwift.hpp +11 -0
  27. package/nitrogen/generated/ios/swift/HybridLiteRTLMSpec.swift +1 -0
  28. package/nitrogen/generated/ios/swift/HybridLiteRTLMSpec_cxx.swift +12 -0
  29. package/nitrogen/generated/ios/swift/ModelCapabilities.swift +29 -0
  30. package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.cpp +1 -0
  31. package/nitrogen/generated/shared/c++/HybridLiteRTLMSpec.hpp +4 -0
  32. package/nitrogen/generated/shared/c++/ModelCapabilities.hpp +83 -0
  33. package/package.json +1 -1
  34. package/src/index.ts +1 -0
  35. package/src/specs/LiteRTLM.nitro.ts +17 -0
@@ -163,9 +163,9 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
163
163
  try {
164
164
  // Early GPU hardware check: probe for OpenCL library.
165
165
  // LiteRT-LM's GPU delegate requires OpenCL, which is absent on
166
- // most Samsung/Qualcomm devices. Log a warning fallback will
167
- // handle it gracefully below.
168
- if (backend == Backend.GPU) {
166
+ // most Samsung/Qualcomm devices. Probe once and cache the result —
167
+ // needed for both GPU main backend and multimodal vision backend.
168
+ if (openCLAvailable == null) {
169
169
  val hasOpenCL = openCLAvailable ?: run {
170
170
  val result = try {
171
171
  System.loadLibrary("OpenCL")
@@ -244,17 +244,38 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
244
244
  }
245
245
  }
246
246
 
247
- // Map our Backend enum to LiteRT-LM Backend sealed class
247
+ // Map our Backend enum to LiteRT-LM Backend sealed class.
248
+ // If hardware is unavailable, skip directly to CPU to avoid native
249
+ // crashes (SIGSEGV) that Kotlin's try/catch cannot intercept.
248
250
  val lmBackend = when (backend) {
249
- Backend.GPU -> com.google.ai.edge.litertlm.Backend.GPU()
251
+ Backend.GPU -> {
252
+ val hasOpenCL = openCLAvailable ?: false
253
+ if (hasOpenCL) {
254
+ com.google.ai.edge.litertlm.Backend.GPU()
255
+ } else {
256
+ Log.w(TAG, "GPU requested but OpenCL unavailable — using CPU directly")
257
+ backend = Backend.CPU
258
+ com.google.ai.edge.litertlm.Backend.CPU()
259
+ }
260
+ }
250
261
  Backend.NPU -> {
251
- Log.i(TAG, "NPU backend requested - requires hardware support")
252
- com.google.ai.edge.litertlm.Backend.NPU()
262
+ val nativeLibDir = LiteRTLMInitProvider.applicationContext?.applicationInfo?.nativeLibraryDir
263
+ Log.i(TAG, "NPU backend requested - nativeLibraryDir=$nativeLibDir")
264
+ if (nativeLibDir != null) {
265
+ com.google.ai.edge.litertlm.Backend.NPU(nativeLibraryDir = nativeLibDir)
266
+ } else {
267
+ Log.w(TAG, "NPU requested but nativeLibraryDir unavailable — using CPU directly")
268
+ backend = Backend.CPU
269
+ com.google.ai.edge.litertlm.Backend.CPU()
270
+ }
253
271
  }
254
272
  else -> com.google.ai.edge.litertlm.Backend.CPU()
255
273
  }
256
274
 
257
- val lmVisionBackend = if (isMultimodal) com.google.ai.edge.litertlm.Backend.GPU() else null
275
+ val lmVisionBackend = if (isMultimodal) {
276
+ if (openCLAvailable == true) com.google.ai.edge.litertlm.Backend.GPU()
277
+ else com.google.ai.edge.litertlm.Backend.CPU()
278
+ } else null
258
279
  val lmAudioBackend = if (isMultimodal) com.google.ai.edge.litertlm.Backend.CPU() else null
259
280
 
260
281
  Log.i(TAG, "Backend config: main=$lmBackend, vision=$lmVisionBackend, audio=$lmAudioBackend, multimodal=$isMultimodal")
@@ -558,6 +579,18 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
558
579
  )
559
580
  }
560
581
 
582
+ override fun checkModelCapabilities(modelPath: String): ModelCapabilities {
583
+ var supportsSpeculativeDecoding = false
584
+ try {
585
+ com.google.ai.edge.litertlm.Capabilities(modelPath).use {
586
+ supportsSpeculativeDecoding = it.hasSpeculativeDecodingSupport()
587
+ }
588
+ } catch (e: Exception) {
589
+ Log.w(TAG, "checkModelCapabilities: failed to query capabilities: ${e.message}")
590
+ }
591
+ return ModelCapabilities(supportsSpeculativeDecoding = supportsSpeculativeDecoding)
592
+ }
593
+
561
594
  override fun getActiveBackend(): Backend = backend
562
595
 
563
596
  override fun stopGeneration() {
package/app.plugin.js CHANGED
@@ -2,10 +2,11 @@
2
2
  * Expo config plugin for react-native-litert-lm.
3
3
  *
4
4
  * Ensures correct build settings for the LiteRT-LM native module:
5
- * - Android: minSdkVersion 26
5
+ * - Android: minSdkVersion 26, Kotlin 2.3.0 (required by litertlm-android AAR)
6
6
  */
7
7
  const {
8
8
  withGradleProperties,
9
+ withProjectBuildGradle,
9
10
  } = require('@expo/config-plugins');
10
11
 
11
12
  function withLiteRTLM(config) {
@@ -28,6 +29,24 @@ function withLiteRTLM(config) {
28
29
  return config;
29
30
  });
30
31
 
32
+ // Android: Pin Kotlin Gradle plugin to 2.3.0
33
+ // The litertlm-android AAR uses Kotlin 2.3.0 metadata which cannot be read
34
+ // by older compilers. This forces the project-level Kotlin plugin to 2.3.0.
35
+ config = withProjectBuildGradle(config, (config) => {
36
+ if (config.modResults.language === 'groovy') {
37
+ const contents = config.modResults.contents;
38
+
39
+ if (!contents.includes("kotlin-gradle-plugin:2.3.0")) {
40
+ config.modResults.contents = contents.replace(
41
+ "classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')",
42
+ "classpath('org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.0')"
43
+ );
44
+ }
45
+ }
46
+
47
+ return config;
48
+ });
49
+
31
50
  return config;
32
51
  }
33
52
 
@@ -142,6 +142,13 @@ public class HybridLiteRTLM: HybridLiteRTLMSpec_base, HybridLiteRTLMSpec_protoco
142
142
  )
143
143
  }
144
144
 
145
+ public func checkModelCapabilities(modelPath: String) throws -> ModelCapabilities {
146
+ // iOS LiteRT-LM C API doesn't expose a Capabilities class like Android.
147
+ // Return safe defaults — speculative decoding support can be detected
148
+ // at engine init time on iOS.
149
+ return ModelCapabilities(supportsSpeculativeDecoding: false)
150
+ }
151
+
145
152
  public func getActiveBackend() throws -> Backend {
146
153
  return backend
147
154
  }
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Backend } from "./specs/LiteRTLM.nitro";
2
- export type { LiteRTLM, LLMConfig, Message, Backend, Role, GenerationStats, MemoryUsage,
2
+ export type { LiteRTLM, LLMConfig, Message, Backend, Role, GenerationStats, MemoryUsage, ModelCapabilities,
3
3
  /** New in v0.5: pass to execute() instead of individual send methods */
4
4
  MultimodalPart, PartType,
5
5
  /** Tool calling types */
@@ -207,6 +207,14 @@ export interface MemoryUsage {
207
207
  /** Whether the system considers memory low */
208
208
  isLowMemory: boolean;
209
209
  }
210
+ /**
211
+ * Model capability flags queried from the model file at runtime.
212
+ * Uses the LiteRT-LM Capabilities API to inspect compiled model metadata.
213
+ */
214
+ export interface ModelCapabilities {
215
+ /** Whether the model binary supports multi-token prediction (speculative decoding). */
216
+ supportsSpeculativeDecoding: boolean;
217
+ }
210
218
  /**
211
219
  * LiteRT-LM: High-performance LLM inference engine.
212
220
  * Supports Gemma 4, Gemma 3n, Phi-4, Qwen, and other .litertlm models.
@@ -356,6 +364,13 @@ export interface LiteRTLM extends HybridObject<{
356
364
  * No-op if nothing is generating.
357
365
  */
358
366
  stopGeneration(): void;
367
+ /**
368
+ * Query model capabilities from the compiled model file.
369
+ * Does NOT require loadModel() — reads metadata directly from disk.
370
+ * @param modelPath Absolute path to the .litertlm model file.
371
+ * @returns Capabilities flags (e.g. speculative decoding support).
372
+ */
373
+ checkModelCapabilities(modelPath: string): ModelCapabilities;
359
374
  /**
360
375
  * Release all native resources.
361
376
  * Call this when done with the LLM instance.
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
15
15
  using namespace facebook;
16
16
 
17
17
  /**
18
- * The C++ JNI bridge between the C++ enum "Backend" and the the Kotlin enum "Backend".
18
+ * The C++ JNI bridge between the C++ enum "Backend" and the Kotlin enum "Backend".
19
19
  */
20
20
  struct JBackend final: public jni::JavaClass<JBackend> {
21
21
  public:
@@ -20,7 +20,7 @@ namespace margelo::nitro::litertlm {
20
20
  using namespace facebook;
21
21
 
22
22
  /**
23
- * The C++ JNI bridge between the C++ struct "ExecuteResult" and the the Kotlin data class "ExecuteResult".
23
+ * The C++ JNI bridge between the C++ struct "ExecuteResult" and the Kotlin data class "ExecuteResult".
24
24
  */
25
25
  struct JExecuteResult final: public jni::JavaClass<JExecuteResult> {
26
26
  public:
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "GenerationStats" and the the Kotlin data class "GenerationStats".
20
+ * The C++ JNI bridge between the C++ struct "GenerationStats" and the Kotlin data class "GenerationStats".
21
21
  */
22
22
  struct JGenerationStats final: public jni::JavaClass<JGenerationStats> {
23
23
  public:
@@ -21,6 +21,8 @@ namespace margelo::nitro::litertlm { struct GenerationStats; }
21
21
  namespace margelo::nitro::litertlm { struct MemoryUsage; }
22
22
  // Forward declaration of `Backend` to properly resolve imports.
23
23
  namespace margelo::nitro::litertlm { enum class Backend; }
24
+ // Forward declaration of `ModelCapabilities` to properly resolve imports.
25
+ namespace margelo::nitro::litertlm { struct ModelCapabilities; }
24
26
  // Forward declaration of `LLMConfig` to properly resolve imports.
25
27
  namespace margelo::nitro::litertlm { struct LLMConfig; }
26
28
  // Forward declaration of `ToolDefinition` to properly resolve imports.
@@ -51,6 +53,8 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
51
53
  #include "JMemoryUsage.hpp"
52
54
  #include "Backend.hpp"
53
55
  #include "JBackend.hpp"
56
+ #include "ModelCapabilities.hpp"
57
+ #include "JModelCapabilities.hpp"
54
58
  #include "LLMConfig.hpp"
55
59
  #include <optional>
56
60
  #include "JLLMConfig.hpp"
@@ -363,6 +367,11 @@ namespace margelo::nitro::litertlm {
363
367
  static const auto method = _javaPart->javaClassStatic()->getMethod<void()>("stopGeneration");
364
368
  method(_javaPart);
365
369
  }
370
+ ModelCapabilities JHybridLiteRTLMSpec::checkModelCapabilities(const std::string& modelPath) {
371
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JModelCapabilities>(jni::alias_ref<jni::JString> /* modelPath */)>("checkModelCapabilities");
372
+ auto __result = method(_javaPart, jni::make_jstring(modelPath));
373
+ return __result->toCpp();
374
+ }
366
375
  void JHybridLiteRTLMSpec::close() {
367
376
  static const auto method = _javaPart->javaClassStatic()->getMethod<void()>("close");
368
377
  method(_javaPart);
@@ -74,6 +74,7 @@ namespace margelo::nitro::litertlm {
74
74
  std::shared_ptr<Promise<ExecuteResult>> sendToolResponse(const std::vector<ToolResponse>& responses, const std::optional<std::function<void(const std::string& /* token */, bool /* done */)>>& onToken) override;
75
75
  Backend getActiveBackend() override;
76
76
  void stopGeneration() override;
77
+ ModelCapabilities checkModelCapabilities(const std::string& modelPath) override;
77
78
  void close() override;
78
79
 
79
80
  private:
@@ -23,7 +23,7 @@ namespace margelo::nitro::litertlm {
23
23
  using namespace facebook;
24
24
 
25
25
  /**
26
- * The C++ JNI bridge between the C++ struct "LLMConfig" and the the Kotlin data class "LLMConfig".
26
+ * The C++ JNI bridge between the C++ struct "LLMConfig" and the Kotlin data class "LLMConfig".
27
27
  */
28
28
  struct JLLMConfig final: public jni::JavaClass<JLLMConfig> {
29
29
  public:
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "MemoryUsage" and the the Kotlin data class "MemoryUsage".
20
+ * The C++ JNI bridge between the C++ struct "MemoryUsage" and the Kotlin data class "MemoryUsage".
21
21
  */
22
22
  struct JMemoryUsage final: public jni::JavaClass<JMemoryUsage> {
23
23
  public:
@@ -19,7 +19,7 @@ namespace margelo::nitro::litertlm {
19
19
  using namespace facebook;
20
20
 
21
21
  /**
22
- * The C++ JNI bridge between the C++ struct "Message" and the the Kotlin data class "Message".
22
+ * The C++ JNI bridge between the C++ struct "Message" and the Kotlin data class "Message".
23
23
  */
24
24
  struct JMessage final: public jni::JavaClass<JMessage> {
25
25
  public:
@@ -0,0 +1,57 @@
1
+ ///
2
+ /// JModelCapabilities.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include "ModelCapabilities.hpp"
12
+
13
+
14
+
15
+ namespace margelo::nitro::litertlm {
16
+
17
+ using namespace facebook;
18
+
19
+ /**
20
+ * The C++ JNI bridge between the C++ struct "ModelCapabilities" and the Kotlin data class "ModelCapabilities".
21
+ */
22
+ struct JModelCapabilities final: public jni::JavaClass<JModelCapabilities> {
23
+ public:
24
+ static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/dev/litert/litertlm/ModelCapabilities;";
25
+
26
+ public:
27
+ /**
28
+ * Convert this Java/Kotlin-based struct to the C++ struct ModelCapabilities by copying all values to C++.
29
+ */
30
+ [[maybe_unused]]
31
+ [[nodiscard]]
32
+ ModelCapabilities toCpp() const {
33
+ static const auto clazz = javaClassStatic();
34
+ static const auto fieldSupportsSpeculativeDecoding = clazz->getField<jboolean>("supportsSpeculativeDecoding");
35
+ jboolean supportsSpeculativeDecoding = this->getFieldValue(fieldSupportsSpeculativeDecoding);
36
+ return ModelCapabilities(
37
+ static_cast<bool>(supportsSpeculativeDecoding)
38
+ );
39
+ }
40
+
41
+ public:
42
+ /**
43
+ * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
44
+ */
45
+ [[maybe_unused]]
46
+ static jni::local_ref<JModelCapabilities::javaobject> fromCpp(const ModelCapabilities& value) {
47
+ using JSignature = JModelCapabilities(jboolean);
48
+ static const auto clazz = javaClassStatic();
49
+ static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
50
+ return create(
51
+ clazz,
52
+ value.supportsSpeculativeDecoding
53
+ );
54
+ }
55
+ };
56
+
57
+ } // namespace margelo::nitro::litertlm
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "ModelFile" and the the Kotlin data class "ModelFile".
20
+ * The C++ JNI bridge between the C++ struct "ModelFile" and the Kotlin data class "ModelFile".
21
21
  */
22
22
  struct JModelFile final: public jni::JavaClass<JModelFile> {
23
23
  public:
@@ -22,7 +22,7 @@ namespace margelo::nitro::litertlm {
22
22
  using namespace facebook;
23
23
 
24
24
  /**
25
- * The C++ JNI bridge between the C++ struct "MultimodalPart" and the the Kotlin data class "MultimodalPart".
25
+ * The C++ JNI bridge between the C++ struct "MultimodalPart" and the Kotlin data class "MultimodalPart".
26
26
  */
27
27
  struct JMultimodalPart final: public jni::JavaClass<JMultimodalPart> {
28
28
  public:
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
15
15
  using namespace facebook;
16
16
 
17
17
  /**
18
- * The C++ JNI bridge between the C++ enum "PartType" and the the Kotlin enum "PartType".
18
+ * The C++ JNI bridge between the C++ enum "PartType" and the Kotlin enum "PartType".
19
19
  */
20
20
  struct JPartType final: public jni::JavaClass<JPartType> {
21
21
  public:
@@ -15,7 +15,7 @@ namespace margelo::nitro::litertlm {
15
15
  using namespace facebook;
16
16
 
17
17
  /**
18
- * The C++ JNI bridge between the C++ enum "Role" and the the Kotlin enum "Role".
18
+ * The C++ JNI bridge between the C++ enum "Role" and the Kotlin enum "Role".
19
19
  */
20
20
  struct JRole final: public jni::JavaClass<JRole> {
21
21
  public:
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "ToolCall" and the the Kotlin data class "ToolCall".
20
+ * The C++ JNI bridge between the C++ struct "ToolCall" and the Kotlin data class "ToolCall".
21
21
  */
22
22
  struct JToolCall final: public jni::JavaClass<JToolCall> {
23
23
  public:
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "ToolDefinition" and the the Kotlin data class "ToolDefinition".
20
+ * The C++ JNI bridge between the C++ struct "ToolDefinition" and the Kotlin data class "ToolDefinition".
21
21
  */
22
22
  struct JToolDefinition final: public jni::JavaClass<JToolDefinition> {
23
23
  public:
@@ -17,7 +17,7 @@ namespace margelo::nitro::litertlm {
17
17
  using namespace facebook;
18
18
 
19
19
  /**
20
- * The C++ JNI bridge between the C++ struct "ToolResponse" and the the Kotlin data class "ToolResponse".
20
+ * The C++ JNI bridge between the C++ struct "ToolResponse" and the Kotlin data class "ToolResponse".
21
21
  */
22
22
  struct JToolResponse final: public jni::JavaClass<JToolResponse> {
23
23
  public:
@@ -139,6 +139,10 @@ abstract class HybridLiteRTLMSpec: HybridObject() {
139
139
  @Keep
140
140
  abstract fun stopGeneration(): Unit
141
141
 
142
+ @DoNotStrip
143
+ @Keep
144
+ abstract fun checkModelCapabilities(modelPath: String): ModelCapabilities
145
+
142
146
  @DoNotStrip
143
147
  @Keep
144
148
  abstract fun close(): Unit
@@ -0,0 +1,51 @@
1
+ ///
2
+ /// ModelCapabilities.kt
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ package com.margelo.nitro.dev.litert.litertlm
9
+
10
+ import androidx.annotation.Keep
11
+ import com.facebook.proguard.annotations.DoNotStrip
12
+ import java.util.Objects
13
+
14
+
15
+ /**
16
+ * Represents the JavaScript object/struct "ModelCapabilities".
17
+ */
18
+ @DoNotStrip
19
+ @Keep
20
+ data class ModelCapabilities(
21
+ @DoNotStrip
22
+ @Keep
23
+ val supportsSpeculativeDecoding: Boolean
24
+ ) {
25
+ /* primary constructor */
26
+
27
+ override fun equals(other: Any?): Boolean {
28
+ if (this === other) return true
29
+ if (other !is ModelCapabilities) return false
30
+ return Objects.deepEquals(this.supportsSpeculativeDecoding, other.supportsSpeculativeDecoding)
31
+ }
32
+
33
+ override fun hashCode(): Int {
34
+ return arrayOf<Any?>(
35
+ supportsSpeculativeDecoding
36
+ ).contentDeepHashCode()
37
+ }
38
+
39
+ companion object {
40
+ /**
41
+ * Constructor called from C++
42
+ */
43
+ @DoNotStrip
44
+ @Keep
45
+ @Suppress("unused")
46
+ @JvmStatic
47
+ private fun fromCpp(supportsSpeculativeDecoding: Boolean): ModelCapabilities {
48
+ return ModelCapabilities(supportsSpeculativeDecoding)
49
+ }
50
+ }
51
+ }
@@ -26,6 +26,8 @@ namespace margelo::nitro::litertlm { struct LLMConfig; }
26
26
  namespace margelo::nitro::litertlm { struct MemoryUsage; }
27
27
  // Forward declaration of `Message` to properly resolve imports.
28
28
  namespace margelo::nitro::litertlm { struct Message; }
29
+ // Forward declaration of `ModelCapabilities` to properly resolve imports.
30
+ namespace margelo::nitro::litertlm { struct ModelCapabilities; }
29
31
  // Forward declaration of `ModelFile` to properly resolve imports.
30
32
  namespace margelo::nitro::litertlm { struct ModelFile; }
31
33
  // Forward declaration of `MultimodalPart` to properly resolve imports.
@@ -56,6 +58,7 @@ namespace LiteRTLM { class HybridModelStoreSpec_cxx; }
56
58
  #include "LLMConfig.hpp"
57
59
  #include "MemoryUsage.hpp"
58
60
  #include "Message.hpp"
61
+ #include "ModelCapabilities.hpp"
59
62
  #include "ModelFile.hpp"
60
63
  #include "MultimodalPart.hpp"
61
64
  #include "PartType.hpp"
@@ -541,6 +544,15 @@ namespace margelo::nitro::litertlm::bridge::swift {
541
544
  return Result<Backend>::withError(error);
542
545
  }
543
546
 
547
+ // pragma MARK: Result<ModelCapabilities>
548
+ using Result_ModelCapabilities_ = Result<ModelCapabilities>;
549
+ inline Result_ModelCapabilities_ create_Result_ModelCapabilities_(const ModelCapabilities& value) noexcept {
550
+ return Result<ModelCapabilities>::withValue(value);
551
+ }
552
+ inline Result_ModelCapabilities_ create_Result_ModelCapabilities_(const std::exception_ptr& error) noexcept {
553
+ return Result<ModelCapabilities>::withError(error);
554
+ }
555
+
544
556
  // pragma MARK: std::vector<ModelFile>
545
557
  /**
546
558
  * Specialized version of `std::vector<ModelFile>`.
@@ -24,6 +24,8 @@ namespace margelo::nitro::litertlm { struct LLMConfig; }
24
24
  namespace margelo::nitro::litertlm { struct MemoryUsage; }
25
25
  // Forward declaration of `Message` to properly resolve imports.
26
26
  namespace margelo::nitro::litertlm { struct Message; }
27
+ // Forward declaration of `ModelCapabilities` to properly resolve imports.
28
+ namespace margelo::nitro::litertlm { struct ModelCapabilities; }
27
29
  // Forward declaration of `ModelFile` to properly resolve imports.
28
30
  namespace margelo::nitro::litertlm { struct ModelFile; }
29
31
  // Forward declaration of `MultimodalPart` to properly resolve imports.
@@ -48,6 +50,7 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
48
50
  #include "LLMConfig.hpp"
49
51
  #include "MemoryUsage.hpp"
50
52
  #include "Message.hpp"
53
+ #include "ModelCapabilities.hpp"
51
54
  #include "ModelFile.hpp"
52
55
  #include "MultimodalPart.hpp"
53
56
  #include "PartType.hpp"
@@ -38,6 +38,8 @@ namespace margelo::nitro::litertlm { struct GenerationStats; }
38
38
  namespace margelo::nitro::litertlm { struct MemoryUsage; }
39
39
  // Forward declaration of `ToolResponse` to properly resolve imports.
40
40
  namespace margelo::nitro::litertlm { struct ToolResponse; }
41
+ // Forward declaration of `ModelCapabilities` to properly resolve imports.
42
+ namespace margelo::nitro::litertlm { struct ModelCapabilities; }
41
43
 
42
44
  #include <NitroModules/Promise.hpp>
43
45
  #include <string>
@@ -58,6 +60,7 @@ namespace margelo::nitro::litertlm { struct ToolResponse; }
58
60
  #include "GenerationStats.hpp"
59
61
  #include "MemoryUsage.hpp"
60
62
  #include "ToolResponse.hpp"
63
+ #include "ModelCapabilities.hpp"
61
64
 
62
65
  #include "LiteRTLM-Swift-Cxx-Umbrella.hpp"
63
66
 
@@ -265,6 +268,14 @@ namespace margelo::nitro::litertlm {
265
268
  std::rethrow_exception(__result.error());
266
269
  }
267
270
  }
271
+ inline ModelCapabilities checkModelCapabilities(const std::string& modelPath) override {
272
+ auto __result = _swiftPart.checkModelCapabilities(modelPath);
273
+ if (__result.hasError()) [[unlikely]] {
274
+ std::rethrow_exception(__result.error());
275
+ }
276
+ auto __value = std::move(__result.value());
277
+ return __value;
278
+ }
268
279
  inline void close() override {
269
280
  auto __result = _swiftPart.close();
270
281
  if (__result.hasError()) [[unlikely]] {
@@ -33,6 +33,7 @@ public protocol HybridLiteRTLMSpec_protocol: HybridObject {
33
33
  func sendToolResponse(responses: [ToolResponse], onToken: ((_ token: String, _ done: Bool) -> Void)?) throws -> Promise<ExecuteResult>
34
34
  func getActiveBackend() throws -> Backend
35
35
  func stopGeneration() throws -> Void
36
+ func checkModelCapabilities(modelPath: String) throws -> ModelCapabilities
36
37
  func close() throws -> Void
37
38
  }
38
39
 
@@ -503,6 +503,18 @@ open class HybridLiteRTLMSpec_cxx {
503
503
  }
504
504
  }
505
505
 
506
+ @inline(__always)
507
+ public final func checkModelCapabilities(modelPath: std.string) -> bridge.Result_ModelCapabilities_ {
508
+ do {
509
+ let __result = try self.__implementation.checkModelCapabilities(modelPath: String(modelPath))
510
+ let __resultCpp = __result
511
+ return bridge.create_Result_ModelCapabilities_(__resultCpp)
512
+ } catch (let __error) {
513
+ let __exceptionPtr = __error.toCpp()
514
+ return bridge.create_Result_ModelCapabilities_(__exceptionPtr)
515
+ }
516
+ }
517
+
506
518
  @inline(__always)
507
519
  public final func close() -> bridge.Result_void_ {
508
520
  do {
@@ -0,0 +1,29 @@
1
+ ///
2
+ /// ModelCapabilities.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ import NitroModules
9
+
10
+ /**
11
+ * Represents an instance of `ModelCapabilities`, backed by a C++ struct.
12
+ */
13
+ public typealias ModelCapabilities = margelo.nitro.litertlm.ModelCapabilities
14
+
15
+ public extension ModelCapabilities {
16
+ private typealias bridge = margelo.nitro.litertlm.bridge.swift
17
+
18
+ /**
19
+ * Create a new instance of `ModelCapabilities`.
20
+ */
21
+ init(supportsSpeculativeDecoding: Bool) {
22
+ self.init(supportsSpeculativeDecoding)
23
+ }
24
+
25
+ @inline(__always)
26
+ var supportsSpeculativeDecoding: Bool {
27
+ return self.__supportsSpeculativeDecoding
28
+ }
29
+ }
@@ -34,6 +34,7 @@ namespace margelo::nitro::litertlm {
34
34
  prototype.registerHybridMethod("sendToolResponse", &HybridLiteRTLMSpec::sendToolResponse);
35
35
  prototype.registerHybridMethod("getActiveBackend", &HybridLiteRTLMSpec::getActiveBackend);
36
36
  prototype.registerHybridMethod("stopGeneration", &HybridLiteRTLMSpec::stopGeneration);
37
+ prototype.registerHybridMethod("checkModelCapabilities", &HybridLiteRTLMSpec::checkModelCapabilities);
37
38
  prototype.registerHybridMethod("close", &HybridLiteRTLMSpec::close);
38
39
  });
39
40
  }
@@ -29,6 +29,8 @@ namespace margelo::nitro::litertlm { struct MemoryUsage; }
29
29
  namespace margelo::nitro::litertlm { struct ToolResponse; }
30
30
  // Forward declaration of `Backend` to properly resolve imports.
31
31
  namespace margelo::nitro::litertlm { enum class Backend; }
32
+ // Forward declaration of `ModelCapabilities` to properly resolve imports.
33
+ namespace margelo::nitro::litertlm { struct ModelCapabilities; }
32
34
 
33
35
  #include <NitroModules/Promise.hpp>
34
36
  #include <string>
@@ -43,6 +45,7 @@ namespace margelo::nitro::litertlm { enum class Backend; }
43
45
  #include "MemoryUsage.hpp"
44
46
  #include "ToolResponse.hpp"
45
47
  #include "Backend.hpp"
48
+ #include "ModelCapabilities.hpp"
46
49
 
47
50
  namespace margelo::nitro::litertlm {
48
51
 
@@ -95,6 +98,7 @@ namespace margelo::nitro::litertlm {
95
98
  virtual std::shared_ptr<Promise<ExecuteResult>> sendToolResponse(const std::vector<ToolResponse>& responses, const std::optional<std::function<void(const std::string& /* token */, bool /* done */)>>& onToken) = 0;
96
99
  virtual Backend getActiveBackend() = 0;
97
100
  virtual void stopGeneration() = 0;
101
+ virtual ModelCapabilities checkModelCapabilities(const std::string& modelPath) = 0;
98
102
  virtual void close() = 0;
99
103
 
100
104
  protected:
@@ -0,0 +1,83 @@
1
+ ///
2
+ /// ModelCapabilities.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
11
+ #include <NitroModules/JSIConverter.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
16
+ #include <NitroModules/NitroDefines.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/JSIHelpers.hpp>)
21
+ #include <NitroModules/JSIHelpers.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+ #if __has_include(<NitroModules/PropNameIDCache.hpp>)
26
+ #include <NitroModules/PropNameIDCache.hpp>
27
+ #else
28
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
29
+ #endif
30
+
31
+
32
+
33
+
34
+
35
+ namespace margelo::nitro::litertlm {
36
+
37
+ /**
38
+ * A struct which can be represented as a JavaScript object (ModelCapabilities).
39
+ */
40
+ struct ModelCapabilities final {
41
+ public:
42
+ bool supportsSpeculativeDecoding SWIFT_PRIVATE;
43
+
44
+ public:
45
+ ModelCapabilities() = default;
46
+ explicit ModelCapabilities(bool supportsSpeculativeDecoding): supportsSpeculativeDecoding(supportsSpeculativeDecoding) {}
47
+
48
+ public:
49
+ friend bool operator==(const ModelCapabilities& lhs, const ModelCapabilities& rhs) = default;
50
+ };
51
+
52
+ } // namespace margelo::nitro::litertlm
53
+
54
+ namespace margelo::nitro {
55
+
56
+ // C++ ModelCapabilities <> JS ModelCapabilities (object)
57
+ template <>
58
+ struct JSIConverter<margelo::nitro::litertlm::ModelCapabilities> final {
59
+ static inline margelo::nitro::litertlm::ModelCapabilities fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
60
+ jsi::Object obj = arg.asObject(runtime);
61
+ return margelo::nitro::litertlm::ModelCapabilities(
62
+ JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding")))
63
+ );
64
+ }
65
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::litertlm::ModelCapabilities& arg) {
66
+ jsi::Object obj(runtime);
67
+ obj.setProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding"), JSIConverter<bool>::toJSI(runtime, arg.supportsSpeculativeDecoding));
68
+ return obj;
69
+ }
70
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
71
+ if (!value.isObject()) {
72
+ return false;
73
+ }
74
+ jsi::Object obj = value.getObject(runtime);
75
+ if (!nitro::isPlainObject(runtime, obj)) {
76
+ return false;
77
+ }
78
+ if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "supportsSpeculativeDecoding")))) return false;
79
+ return true;
80
+ }
81
+ };
82
+
83
+ } // namespace margelo::nitro
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dr33m/react-native-litert-lm",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "litertLm": {
5
5
  "version": "0.12.0",
6
6
  "androidMavenVersion": "0.12.0",
package/src/index.ts CHANGED
@@ -18,6 +18,7 @@ export type {
18
18
  Role,
19
19
  GenerationStats,
20
20
  MemoryUsage,
21
+ ModelCapabilities,
21
22
  /** New in v0.5: pass to execute() instead of individual send methods */
22
23
  MultimodalPart,
23
24
  PartType,
@@ -232,6 +232,15 @@ export interface MemoryUsage {
232
232
  isLowMemory: boolean;
233
233
  }
234
234
 
235
+ /**
236
+ * Model capability flags queried from the model file at runtime.
237
+ * Uses the LiteRT-LM Capabilities API to inspect compiled model metadata.
238
+ */
239
+ export interface ModelCapabilities {
240
+ /** Whether the model binary supports multi-token prediction (speculative decoding). */
241
+ supportsSpeculativeDecoding: boolean;
242
+ }
243
+
235
244
  /**
236
245
  * LiteRT-LM: High-performance LLM inference engine.
237
246
  * Supports Gemma 4, Gemma 3n, Phi-4, Qwen, and other .litertlm models.
@@ -420,6 +429,14 @@ export interface LiteRTLM extends HybridObject<{
420
429
  */
421
430
  stopGeneration(): void;
422
431
 
432
+ /**
433
+ * Query model capabilities from the compiled model file.
434
+ * Does NOT require loadModel() — reads metadata directly from disk.
435
+ * @param modelPath Absolute path to the .litertlm model file.
436
+ * @returns Capabilities flags (e.g. speculative decoding support).
437
+ */
438
+ checkModelCapabilities(modelPath: string): ModelCapabilities;
439
+
423
440
  /**
424
441
  * Release all native resources.
425
442
  * Call this when done with the LLM instance.