@dr33m/react-native-litert-lm 0.5.5 → 0.5.6

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.
@@ -575,7 +575,10 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
575
575
  return lastStats
576
576
  }
577
577
 
578
- override fun getMemoryUsage(): MemoryUsage {
578
+ /** Shared by the public [getMemoryUsage] override and the pre-flight guard
579
+ * in [execute] — both need the same real, OS-level reading, not an
580
+ * estimate. */
581
+ private fun currentMemoryUsage(): MemoryUsage {
579
582
  // Native heap: allocated bytes from Debug APIs (most accurate for native allocations)
580
583
  val nativeHeapBytes = Debug.getNativeHeapAllocatedSize().toDouble()
581
584
 
@@ -619,6 +622,8 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
619
622
  )
620
623
  }
621
624
 
625
+ override fun getMemoryUsage(): MemoryUsage = currentMemoryUsage()
626
+
622
627
  override fun checkModelCapabilities(modelPath: String): ModelCapabilities {
623
628
  var supportsSpeculativeDecoding = false
624
629
  try {
@@ -784,6 +789,16 @@ class HybridLiteRTLM : HybridLiteRTLMSpec() {
784
789
 
785
790
  return Promise.parallel {
786
791
  ensureLoaded()
792
+
793
+ // Refuse rather than risk it: growing the KV-cache under real memory
794
+ // pressure can fail at the native engine level in a way that never
795
+ // surfaces as a catchable Kotlin exception — it takes the whole
796
+ // process down. A plain RuntimeException here is a normal rejected
797
+ // Promise for callers, same contract as any other execute() failure.
798
+ if (currentMemoryUsage().isLowMemory) {
799
+ throw RuntimeException("LiteRTLM: Device memory is critically low; refusing to continue generation.")
800
+ }
801
+
787
802
  // Clear any previous tool calls before new inference
788
803
  pendingToolCalls.clear()
789
804
 
@@ -80,6 +80,18 @@ extension HybridLiteRTLM {
80
80
  return
81
81
  }
82
82
 
83
+ // Refuse rather than risk it: growing the KV-cache under real memory
84
+ // pressure can fail inside the underlying C engine in a way that
85
+ // never surfaces as a catchable Swift error — it takes the whole
86
+ // process down (Jetsam or a hard native failure). An NSError here
87
+ // is a normal rejected Promise for callers, same contract as any
88
+ // other execute() failure.
89
+ if Self.currentMemoryUsage().isLowMemory {
90
+ promise.reject(withError: NSError(domain: "LiteRTLM", code: 507,
91
+ userInfo: [NSLocalizedDescriptionKey: "LiteRTLM: Device memory is critically low; refusing to continue generation."]))
92
+ return
93
+ }
94
+
83
95
  let payload: (json: String, tempFiles: [String])
84
96
  do { payload = try self.buildExecutePayload(preprocessed) }
85
97
  catch { promise.reject(withError: error); return }
@@ -111,9 +111,18 @@ public class HybridLiteRTLM: HybridLiteRTLMSpec_base, HybridLiteRTLMSpec_protoco
111
111
  }
112
112
 
113
113
  public func getMemoryUsage() throws -> MemoryUsage {
114
+ return Self.currentMemoryUsage()
115
+ }
116
+
117
+ /// Shared by the public `getMemoryUsage()` override and the pre-flight
118
+ /// guard in `HybridLiteRTLM+Execute.swift` — both need the same real,
119
+ /// OS-level reading, not an estimate. `static` since it needs no
120
+ /// instance state, which also makes it trivially callable from the
121
+ /// extension file.
122
+ static func currentMemoryUsage() -> MemoryUsage {
114
123
  var residentBytes: Double = 0.0
115
124
  var nativeHeapBytes: Double = 0.0
116
-
125
+
117
126
  // Retrieve process resident set size (RSS) via Mach basic task info
118
127
  var info = mach_task_basic_info()
119
128
  var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size / MemoryLayout<integer_t>.size)
@@ -122,18 +131,18 @@ public class HybridLiteRTLM: HybridLiteRTLMSpec_base, HybridLiteRTLMSpec_protoco
122
131
  task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
123
132
  }
124
133
  }
125
-
134
+
126
135
  if kerr == KERN_SUCCESS {
127
136
  residentBytes = Double(info.resident_size)
128
137
  nativeHeapBytes = Double(info.resident_size)
129
138
  }
130
-
139
+
131
140
  // os_proc_available_memory reports actual headroom available before Jetsam termination (iOS 13+)
132
141
  let availableBytes = Double(os_proc_available_memory())
133
-
142
+
134
143
  // Flag memory warning at ~200MB remaining headroom
135
144
  let isLowMemory = availableBytes < 200.0 * 1024.0 * 1024.0
136
-
145
+
137
146
  return MemoryUsage(
138
147
  nativeHeapBytes: nativeHeapBytes,
139
148
  residentBytes: residentBytes,
@@ -10,7 +10,6 @@ package com.margelo.nitro.dev.litert.litertlm
10
10
  import androidx.annotation.Keep
11
11
  import com.facebook.jni.HybridData
12
12
  import com.facebook.proguard.annotations.DoNotStrip
13
- import dalvik.annotation.optimization.FastNative
14
13
 
15
14
 
16
15
  /**
@@ -59,7 +58,6 @@ class Func_void_double_cxx: Func_void_double {
59
58
  override fun invoke(progress: Double): Unit
60
59
  = invoke_cxx(progress)
61
60
 
62
- @FastNative
63
61
  private external fun invoke_cxx(progress: Double): Unit
64
62
  }
65
63
 
@@ -10,7 +10,6 @@ package com.margelo.nitro.dev.litert.litertlm
10
10
  import androidx.annotation.Keep
11
11
  import com.facebook.jni.HybridData
12
12
  import com.facebook.proguard.annotations.DoNotStrip
13
- import dalvik.annotation.optimization.FastNative
14
13
 
15
14
 
16
15
  /**
@@ -59,7 +58,6 @@ class Func_void_std__string_bool_cxx: Func_void_std__string_bool {
59
58
  override fun invoke(token: String, done: Boolean): Unit
60
59
  = invoke_cxx(token,done)
61
60
 
62
- @FastNative
63
61
  private external fun invoke_cxx(token: String, done: Boolean): Unit
64
62
  }
65
63
 
@@ -10,6 +10,7 @@ package com.margelo.nitro.dev.litert.litertlm
10
10
  import androidx.annotation.Keep
11
11
  import com.facebook.jni.HybridData
12
12
  import com.facebook.proguard.annotations.DoNotStrip
13
+ import dalvik.annotation.optimization.FastNative
13
14
  import com.margelo.nitro.core.Promise
14
15
  import com.margelo.nitro.core.HybridObject
15
16
 
@@ -157,6 +158,7 @@ abstract class HybridLiteRTLMSpec: HybridObject() {
157
158
  @Keep
158
159
  protected open class CxxPart(javaPart: HybridLiteRTLMSpec): HybridObject.CxxPart(javaPart) {
159
160
  // C++ JHybridLiteRTLMSpec::CxxPart::initHybrid(...)
161
+ @FastNative
160
162
  external override fun initHybrid(): HybridData
161
163
  }
162
164
  override fun createCxxPart(): CxxPart {
@@ -10,6 +10,7 @@ package com.margelo.nitro.dev.litert.litertlm
10
10
  import androidx.annotation.Keep
11
11
  import com.facebook.jni.HybridData
12
12
  import com.facebook.proguard.annotations.DoNotStrip
13
+ import dalvik.annotation.optimization.FastNative
13
14
  import com.margelo.nitro.core.Promise
14
15
  import com.margelo.nitro.core.HybridObject
15
16
 
@@ -64,6 +65,7 @@ abstract class HybridModelStoreSpec: HybridObject() {
64
65
  @Keep
65
66
  protected open class CxxPart(javaPart: HybridModelStoreSpec): HybridObject.CxxPart(javaPart) {
66
67
  // C++ JHybridModelStoreSpec::CxxPart::initHybrid(...)
68
+ @FastNative
67
69
  external override fun initHybrid(): HybridData
68
70
  }
69
71
  override fun createCxxPart(): CxxPart {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dr33m/react-native-litert-lm",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "litertLm": {
5
5
  "version": "0.12.0",
6
6
  "androidMavenVersion": "0.12.0",