cactus-react-native 1.2.1 → 1.4.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 (214) hide show
  1. package/README.md +555 -8
  2. package/android/CMakeLists.txt +4 -3
  3. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusFileSystem.kt +20 -1
  4. package/android/src/main/jniLibs/arm64-v8a/libcactus.a +0 -0
  5. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.a +0 -0
  6. package/cpp/HybridCactus.cpp +112 -19
  7. package/cpp/HybridCactus.hpp +12 -3
  8. package/cpp/HybridCactusIndex.cpp +325 -0
  9. package/cpp/HybridCactusIndex.hpp +43 -0
  10. package/cpp/HybridCactusUtil.cpp +3 -3
  11. package/cpp/HybridCactusUtil.hpp +2 -1
  12. package/cpp/cactus_ffi.h +83 -2
  13. package/cpp/cactus_util.h +1 -1
  14. package/ios/HybridCactusFileSystem.swift +23 -2
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus.h +2 -0
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_ffi.h +83 -2
  17. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_telemetry.h +656 -0
  18. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/{ffi_utils.h → cactus_utils.h} +104 -17
  19. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +117 -7
  20. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +91 -5
  21. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +15 -6
  22. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Info.plist +0 -0
  23. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  24. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus.h +2 -0
  25. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +83 -2
  26. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_telemetry.h +656 -0
  27. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/{ffi_utils.h → cactus_utils.h} +104 -17
  28. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +117 -7
  29. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +91 -5
  30. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +15 -6
  31. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Info.plist +0 -0
  32. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/_CodeSignature/CodeResources +1 -1
  33. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  34. package/ios/cactus_util.xcframework/Info.plist +4 -4
  35. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/cactus_util.h +1 -1
  36. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/database.h +27 -0
  37. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Info.plist +0 -0
  38. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/cactus_util +0 -0
  39. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/cactus_util.h +1 -1
  40. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/database.h +27 -0
  41. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Info.plist +0 -0
  42. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/_CodeSignature/CodeResources +3 -3
  43. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/cactus_util +0 -0
  44. package/lib/module/api/Database.js +12 -3
  45. package/lib/module/api/Database.js.map +1 -1
  46. package/lib/module/classes/CactusIndex.js +45 -0
  47. package/lib/module/classes/CactusIndex.js.map +1 -0
  48. package/lib/module/classes/CactusLM.js +35 -5
  49. package/lib/module/classes/CactusLM.js.map +1 -1
  50. package/lib/module/classes/CactusSTT.js +17 -5
  51. package/lib/module/classes/CactusSTT.js.map +1 -1
  52. package/lib/module/config/CactusConfig.js +2 -0
  53. package/lib/module/config/CactusConfig.js.map +1 -1
  54. package/lib/module/constants/packageVersion.js +1 -1
  55. package/lib/module/hooks/useCactusIndex.js +175 -0
  56. package/lib/module/hooks/useCactusIndex.js.map +1 -0
  57. package/lib/module/hooks/useCactusLM.js +54 -2
  58. package/lib/module/hooks/useCactusLM.js.map +1 -1
  59. package/lib/module/hooks/useCactusSTT.js +2 -2
  60. package/lib/module/hooks/useCactusSTT.js.map +1 -1
  61. package/lib/module/index.js +2 -0
  62. package/lib/module/index.js.map +1 -1
  63. package/lib/module/native/Cactus.js +24 -13
  64. package/lib/module/native/Cactus.js.map +1 -1
  65. package/lib/module/native/CactusFileSystem.js +3 -0
  66. package/lib/module/native/CactusFileSystem.js.map +1 -1
  67. package/lib/module/native/CactusIndex.js +32 -0
  68. package/lib/module/native/CactusIndex.js.map +1 -0
  69. package/lib/module/native/CactusUtil.js +16 -3
  70. package/lib/module/native/CactusUtil.js.map +1 -1
  71. package/lib/module/native/index.js +1 -0
  72. package/lib/module/native/index.js.map +1 -1
  73. package/lib/module/specs/CactusIndex.nitro.js +4 -0
  74. package/lib/module/specs/CactusIndex.nitro.js.map +1 -0
  75. package/lib/module/telemetry/Telemetry.js +3 -1
  76. package/lib/module/telemetry/Telemetry.js.map +1 -1
  77. package/lib/module/types/CactusIndex.js +2 -0
  78. package/lib/module/types/CactusIndex.js.map +1 -0
  79. package/lib/typescript/src/api/Database.d.ts +4 -1
  80. package/lib/typescript/src/api/Database.d.ts.map +1 -1
  81. package/lib/typescript/src/classes/CactusIndex.d.ts +15 -0
  82. package/lib/typescript/src/classes/CactusIndex.d.ts.map +1 -0
  83. package/lib/typescript/src/classes/CactusLM.d.ts +5 -2
  84. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  85. package/lib/typescript/src/classes/CactusSTT.d.ts +2 -1
  86. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  87. package/lib/typescript/src/config/CactusConfig.d.ts +1 -0
  88. package/lib/typescript/src/config/CactusConfig.d.ts.map +1 -1
  89. package/lib/typescript/src/constants/packageVersion.d.ts +1 -1
  90. package/lib/typescript/src/hooks/useCactusIndex.d.ts +14 -0
  91. package/lib/typescript/src/hooks/useCactusIndex.d.ts.map +1 -0
  92. package/lib/typescript/src/hooks/useCactusLM.d.ts +4 -2
  93. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  94. package/lib/typescript/src/hooks/useCactusSTT.d.ts +1 -1
  95. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  96. package/lib/typescript/src/index.d.ts +4 -1
  97. package/lib/typescript/src/index.d.ts.map +1 -1
  98. package/lib/typescript/src/native/Cactus.d.ts +4 -2
  99. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  100. package/lib/typescript/src/native/CactusFileSystem.d.ts +1 -0
  101. package/lib/typescript/src/native/CactusFileSystem.d.ts.map +1 -1
  102. package/lib/typescript/src/native/CactusIndex.d.ts +12 -0
  103. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -0
  104. package/lib/typescript/src/native/CactusUtil.d.ts.map +1 -1
  105. package/lib/typescript/src/native/index.d.ts +1 -0
  106. package/lib/typescript/src/native/index.d.ts.map +1 -1
  107. package/lib/typescript/src/specs/Cactus.nitro.d.ts +4 -2
  108. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  109. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts +1 -0
  110. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts.map +1 -1
  111. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts +24 -0
  112. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts.map +1 -0
  113. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts +1 -1
  114. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts.map +1 -1
  115. package/lib/typescript/src/types/CactusIndex.d.ts +34 -0
  116. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -0
  117. package/lib/typescript/src/types/CactusLM.d.ts +17 -0
  118. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  119. package/lib/typescript/src/types/CactusSTT.d.ts +1 -1
  120. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  121. package/nitro.json +3 -0
  122. package/nitrogen/generated/android/c++/JDeviceInfo.hpp +1 -1
  123. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +1 -1
  124. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +1 -1
  125. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +1 -1
  126. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +1 -1
  127. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +1 -1
  128. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.cpp +17 -1
  129. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.hpp +2 -1
  130. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.cpp +1 -1
  131. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.hpp +1 -1
  132. package/nitrogen/generated/android/cactus+autolinking.cmake +2 -1
  133. package/nitrogen/generated/android/cactus+autolinking.gradle +1 -1
  134. package/nitrogen/generated/android/cactusOnLoad.cpp +11 -1
  135. package/nitrogen/generated/android/cactusOnLoad.hpp +1 -1
  136. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +1 -1
  137. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/Func_void_double.kt +1 -1
  138. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +1 -1
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +1 -1
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusFileSystemSpec.kt +5 -1
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusImageSpec.kt +1 -1
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/cactusOnLoad.kt +1 -1
  143. package/nitrogen/generated/ios/Cactus+autolinking.rb +1 -1
  144. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +1 -1
  145. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +1 -1
  146. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +1 -1
  147. package/nitrogen/generated/ios/CactusAutolinking.mm +11 -1
  148. package/nitrogen/generated/ios/CactusAutolinking.swift +1 -1
  149. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +1 -1
  150. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +1 -1
  151. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +1 -1
  152. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +1 -1
  153. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.cpp +1 -1
  154. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.hpp +9 -1
  155. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.cpp +1 -1
  156. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.hpp +1 -1
  157. package/nitrogen/generated/ios/swift/DeviceInfo.swift +1 -1
  158. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  159. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +1 -1
  160. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -1
  161. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -1
  162. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -1
  163. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +1 -1
  164. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -1
  165. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +1 -1
  166. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +1 -1
  167. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +1 -1
  168. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +1 -1
  169. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec.swift +2 -1
  170. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec_cxx.swift +20 -1
  171. package/nitrogen/generated/ios/swift/HybridCactusImageSpec.swift +1 -1
  172. package/nitrogen/generated/ios/swift/HybridCactusImageSpec_cxx.swift +1 -1
  173. package/nitrogen/generated/shared/c++/CactusIndexGetResult.hpp +84 -0
  174. package/nitrogen/generated/shared/c++/CactusIndexQueryResult.hpp +79 -0
  175. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +1 -1
  176. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +1 -1
  177. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +1 -1
  178. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +1 -1
  179. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +1 -1
  180. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.cpp +2 -1
  181. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.hpp +2 -1
  182. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.cpp +1 -1
  183. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.hpp +1 -1
  184. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.cpp +27 -0
  185. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.hpp +76 -0
  186. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +3 -1
  187. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +6 -3
  188. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +1 -1
  189. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +2 -2
  190. package/package.json +2 -2
  191. package/src/api/Database.ts +14 -2
  192. package/src/classes/CactusIndex.ts +58 -0
  193. package/src/classes/CactusLM.ts +41 -5
  194. package/src/classes/CactusSTT.ts +19 -6
  195. package/src/config/CactusConfig.ts +3 -0
  196. package/src/constants/packageVersion.ts +1 -1
  197. package/src/hooks/useCactusIndex.ts +195 -0
  198. package/src/hooks/useCactusLM.ts +63 -3
  199. package/src/hooks/useCactusSTT.ts +2 -2
  200. package/src/index.tsx +16 -0
  201. package/src/native/Cactus.ts +40 -13
  202. package/src/native/CactusFileSystem.ts +4 -0
  203. package/src/native/CactusIndex.ts +54 -0
  204. package/src/native/CactusUtil.ts +19 -3
  205. package/src/native/index.ts +1 -0
  206. package/src/specs/Cactus.nitro.ts +13 -2
  207. package/src/specs/CactusFileSystem.nitro.ts +2 -0
  208. package/src/specs/CactusIndex.nitro.ts +31 -0
  209. package/src/specs/CactusUtil.nitro.ts +1 -1
  210. package/src/telemetry/Telemetry.ts +1 -1
  211. package/src/types/CactusIndex.ts +40 -0
  212. package/src/types/CactusLM.ts +21 -0
  213. package/src/types/CactusSTT.ts +1 -1
  214. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.so +0 -0
@@ -0,0 +1,27 @@
1
+ ///
2
+ /// HybridCactusIndexSpec.cpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #include "HybridCactusIndexSpec.hpp"
9
+
10
+ namespace margelo::nitro::cactus {
11
+
12
+ void HybridCactusIndexSpec::loadHybridMethods() {
13
+ // load base methods/properties
14
+ HybridObject::loadHybridMethods();
15
+ // load custom methods/properties
16
+ registerHybrids(this, [](Prototype& prototype) {
17
+ prototype.registerHybridMethod("init", &HybridCactusIndexSpec::init);
18
+ prototype.registerHybridMethod("add", &HybridCactusIndexSpec::add);
19
+ prototype.registerHybridMethod("_delete", &HybridCactusIndexSpec::_delete);
20
+ prototype.registerHybridMethod("get", &HybridCactusIndexSpec::get);
21
+ prototype.registerHybridMethod("query", &HybridCactusIndexSpec::query);
22
+ prototype.registerHybridMethod("compact", &HybridCactusIndexSpec::compact);
23
+ prototype.registerHybridMethod("destroy", &HybridCactusIndexSpec::destroy);
24
+ });
25
+ }
26
+
27
+ } // namespace margelo::nitro::cactus
@@ -0,0 +1,76 @@
1
+ ///
2
+ /// HybridCactusIndexSpec.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/HybridObject.hpp>)
11
+ #include <NitroModules/HybridObject.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+
16
+ // Forward declaration of `CactusIndexGetResult` to properly resolve imports.
17
+ namespace margelo::nitro::cactus { struct CactusIndexGetResult; }
18
+ // Forward declaration of `CactusIndexQueryResult` to properly resolve imports.
19
+ namespace margelo::nitro::cactus { struct CactusIndexQueryResult; }
20
+
21
+ #include <NitroModules/Promise.hpp>
22
+ #include <string>
23
+ #include <vector>
24
+ #include <optional>
25
+ #include "CactusIndexGetResult.hpp"
26
+ #include "CactusIndexQueryResult.hpp"
27
+
28
+ namespace margelo::nitro::cactus {
29
+
30
+ using namespace margelo::nitro;
31
+
32
+ /**
33
+ * An abstract base class for `CactusIndex`
34
+ * Inherit this class to create instances of `HybridCactusIndexSpec` in C++.
35
+ * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
36
+ * @example
37
+ * ```cpp
38
+ * class HybridCactusIndex: public HybridCactusIndexSpec {
39
+ * public:
40
+ * HybridCactusIndex(...): HybridObject(TAG) { ... }
41
+ * // ...
42
+ * };
43
+ * ```
44
+ */
45
+ class HybridCactusIndexSpec: public virtual HybridObject {
46
+ public:
47
+ // Constructor
48
+ explicit HybridCactusIndexSpec(): HybridObject(TAG) { }
49
+
50
+ // Destructor
51
+ ~HybridCactusIndexSpec() override = default;
52
+
53
+ public:
54
+ // Properties
55
+
56
+
57
+ public:
58
+ // Methods
59
+ virtual std::shared_ptr<Promise<void>> init(const std::string& indexPath, double embeddingDim) = 0;
60
+ virtual std::shared_ptr<Promise<void>> add(const std::vector<double>& ids, const std::vector<std::string>& documents, const std::vector<std::vector<double>>& embeddings, const std::optional<std::vector<std::string>>& metadatas) = 0;
61
+ virtual std::shared_ptr<Promise<void>> _delete(const std::vector<double>& ids) = 0;
62
+ virtual std::shared_ptr<Promise<CactusIndexGetResult>> get(const std::vector<double>& ids) = 0;
63
+ virtual std::shared_ptr<Promise<CactusIndexQueryResult>> query(const std::vector<std::vector<double>>& embeddings, const std::optional<std::string>& optionsJson) = 0;
64
+ virtual std::shared_ptr<Promise<void>> compact() = 0;
65
+ virtual std::shared_ptr<Promise<void>> destroy() = 0;
66
+
67
+ protected:
68
+ // Hybrid Setup
69
+ void loadHybridMethods() override;
70
+
71
+ protected:
72
+ // Tag for logging
73
+ static constexpr auto TAG = "CactusIndex";
74
+ };
75
+
76
+ } // namespace margelo::nitro::cactus
@@ -2,7 +2,7 @@
2
2
  /// HybridCactusSpec.cpp
3
3
  /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
4
  /// https://github.com/mrousavy/nitro
5
- /// Copyright © 2025 Marc Rousavy @ Margelo
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
6
  ///
7
7
 
8
8
  #include "HybridCactusSpec.hpp"
@@ -16,6 +16,8 @@ namespace margelo::nitro::cactus {
16
16
  registerHybrids(this, [](Prototype& prototype) {
17
17
  prototype.registerHybridMethod("init", &HybridCactusSpec::init);
18
18
  prototype.registerHybridMethod("complete", &HybridCactusSpec::complete);
19
+ prototype.registerHybridMethod("tokenize", &HybridCactusSpec::tokenize);
20
+ prototype.registerHybridMethod("scoreWindow", &HybridCactusSpec::scoreWindow);
19
21
  prototype.registerHybridMethod("transcribe", &HybridCactusSpec::transcribe);
20
22
  prototype.registerHybridMethod("embed", &HybridCactusSpec::embed);
21
23
  prototype.registerHybridMethod("imageEmbed", &HybridCactusSpec::imageEmbed);
@@ -2,7 +2,7 @@
2
2
  /// HybridCactusSpec.hpp
3
3
  /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
4
  /// https://github.com/mrousavy/nitro
5
- /// Copyright © 2025 Marc Rousavy @ Margelo
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
6
  ///
7
7
 
8
8
  #pragma once
@@ -20,6 +20,7 @@
20
20
  #include <optional>
21
21
  #include <functional>
22
22
  #include <vector>
23
+ #include <variant>
23
24
 
24
25
  namespace margelo::nitro::cactus {
25
26
 
@@ -54,8 +55,10 @@ namespace margelo::nitro::cactus {
54
55
  // Methods
55
56
  virtual std::shared_ptr<Promise<void>> init(const std::string& modelPath, double contextSize, const std::optional<std::string>& corpusDir) = 0;
56
57
  virtual std::shared_ptr<Promise<std::string>> complete(const std::string& messagesJson, double responseBufferSize, const std::optional<std::string>& optionsJson, const std::optional<std::string>& toolsJson, const std::optional<std::function<void(const std::string& /* token */, double /* tokenId */)>>& callback) = 0;
57
- virtual std::shared_ptr<Promise<std::string>> transcribe(const std::string& audioFilePath, const std::string& prompt, double responseBufferSize, const std::optional<std::string>& optionsJson, const std::optional<std::function<void(const std::string& /* token */, double /* tokenId */)>>& callback) = 0;
58
- virtual std::shared_ptr<Promise<std::vector<double>>> embed(const std::string& text, double embeddingBufferSize) = 0;
58
+ virtual std::shared_ptr<Promise<std::vector<double>>> tokenize(const std::string& text) = 0;
59
+ virtual std::shared_ptr<Promise<std::string>> scoreWindow(const std::vector<double>& tokens, double start, double end, double context) = 0;
60
+ virtual std::shared_ptr<Promise<std::string>> transcribe(const std::variant<std::vector<double>, std::string>& audio, const std::string& prompt, double responseBufferSize, const std::optional<std::string>& optionsJson, const std::optional<std::function<void(const std::string& /* token */, double /* tokenId */)>>& callback) = 0;
61
+ virtual std::shared_ptr<Promise<std::vector<double>>> embed(const std::string& text, double embeddingBufferSize, bool normalize) = 0;
59
62
  virtual std::shared_ptr<Promise<std::vector<double>>> imageEmbed(const std::string& imagePath, double embeddingBufferSize) = 0;
60
63
  virtual std::shared_ptr<Promise<std::vector<double>>> audioEmbed(const std::string& audioPath, double embeddingBufferSize) = 0;
61
64
  virtual std::shared_ptr<Promise<void>> reset() = 0;
@@ -2,7 +2,7 @@
2
2
  /// HybridCactusUtilSpec.cpp
3
3
  /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
4
  /// https://github.com/mrousavy/nitro
5
- /// Copyright © 2025 Marc Rousavy @ Margelo
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
6
  ///
7
7
 
8
8
  #include "HybridCactusUtilSpec.hpp"
@@ -2,7 +2,7 @@
2
2
  /// HybridCactusUtilSpec.hpp
3
3
  /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
4
  /// https://github.com/mrousavy/nitro
5
- /// Copyright © 2025 Marc Rousavy @ Margelo
5
+ /// Copyright © 2026 Marc Rousavy @ Margelo
6
6
  ///
7
7
 
8
8
  #pragma once
@@ -51,7 +51,7 @@ namespace margelo::nitro::cactus {
51
51
  public:
52
52
  // Methods
53
53
  virtual std::shared_ptr<Promise<std::string>> registerApp(const std::string& encryptedData) = 0;
54
- virtual std::shared_ptr<Promise<std::optional<std::string>>> getDeviceId() = 0;
54
+ virtual std::shared_ptr<Promise<std::optional<std::string>>> getDeviceId(const std::optional<std::string>& token) = 0;
55
55
  virtual std::shared_ptr<Promise<void>> setAndroidDataDirectory(const std::string& dataDir) = 0;
56
56
 
57
57
  protected:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cactus-react-native",
3
- "version": "1.2.1",
3
+ "version": "1.4.0",
4
4
  "description": "Run AI models locally on mobile devices",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -83,7 +83,7 @@
83
83
  "react": "19.1.0",
84
84
  "react-native": "0.81.1",
85
85
  "react-native-builder-bob": "^0.40.14",
86
- "react-native-nitro-modules": "^0.31.3",
86
+ "react-native-nitro-modules": "^0.31.10",
87
87
  "release-it": "^19.0.4",
88
88
  "turbo": "^2.5.6",
89
89
  "typescript": "^5.9.2"
@@ -4,6 +4,7 @@ import type { LogRecord } from '../telemetry/Telemetry';
4
4
  import { packageVersion } from '../constants/packageVersion';
5
5
  import type { CactusModel } from '../types/CactusModel';
6
6
  import type { CactusSTTModel } from '../types/CactusSTTModel';
7
+ import { CactusConfig } from '../config/CactusConfig';
7
8
 
8
9
  interface CactusModelResponse {
9
10
  name: string;
@@ -47,12 +48,23 @@ export class Database {
47
48
  }
48
49
  }
49
50
 
50
- public static async registerDevice(device_data: DeviceInfo): Promise<string> {
51
+ public static async registerDevice({
52
+ deviceData,
53
+ deviceId,
54
+ }: {
55
+ deviceData?: DeviceInfo;
56
+ deviceId?: string;
57
+ }): Promise<string> {
51
58
  const response = await fetch(
52
59
  `${this.url}/functions/v1/device-registration`,
53
60
  {
54
61
  method: 'POST',
55
- body: JSON.stringify({ device_data }),
62
+ body: JSON.stringify({
63
+ device_data: deviceData,
64
+ device_id: deviceId,
65
+ cactus_pro_key: CactusConfig.cactusProKey,
66
+ }),
67
+ headers: { 'Content-Type': 'application/json' },
56
68
  }
57
69
  );
58
70
 
@@ -0,0 +1,58 @@
1
+ import { CactusIndex as NativeCactusIndex, CactusFileSystem } from '../native';
2
+ import type {
3
+ CactusIndexAddParams,
4
+ CactusIndexGetParams,
5
+ CactusIndexGetResult,
6
+ CactusIndexQueryParams,
7
+ CactusIndexQueryResult,
8
+ CactusIndexDeleteParams,
9
+ } from '../types/CactusIndex';
10
+
11
+ export class CactusIndex {
12
+ private readonly cactusIndex = new NativeCactusIndex();
13
+
14
+ private readonly name: string;
15
+ private readonly embeddingDim: number;
16
+
17
+ constructor(name: string, embeddingDim: number) {
18
+ this.name = name;
19
+ this.embeddingDim = embeddingDim;
20
+ }
21
+
22
+ public async init(): Promise<void> {
23
+ const indexPath = await CactusFileSystem.getIndexPath(this.name);
24
+ return this.cactusIndex.init(indexPath, this.embeddingDim);
25
+ }
26
+
27
+ public add({
28
+ ids,
29
+ documents,
30
+ embeddings,
31
+ metadatas,
32
+ }: CactusIndexAddParams): Promise<void> {
33
+ return this.cactusIndex.add(ids, documents, embeddings, metadatas);
34
+ }
35
+
36
+ public delete({ ids }: CactusIndexDeleteParams): Promise<void> {
37
+ return this.cactusIndex.delete(ids);
38
+ }
39
+
40
+ public get({ ids }: CactusIndexGetParams): Promise<CactusIndexGetResult> {
41
+ return this.cactusIndex.get(ids);
42
+ }
43
+
44
+ public query({
45
+ embeddings,
46
+ options,
47
+ }: CactusIndexQueryParams): Promise<CactusIndexQueryResult> {
48
+ return this.cactusIndex.query(embeddings, options);
49
+ }
50
+
51
+ public compact(): Promise<void> {
52
+ return this.cactusIndex.compact();
53
+ }
54
+
55
+ public destroy(): Promise<void> {
56
+ return this.cactusIndex.destroy();
57
+ }
58
+ }
@@ -3,6 +3,10 @@ import type {
3
3
  CactusLMDownloadParams,
4
4
  CactusLMCompleteParams,
5
5
  CactusLMCompleteResult,
6
+ CactusLMTokenizeParams,
7
+ CactusLMTokenizeResult,
8
+ CactusLMScoreWindowParams,
9
+ CactusLMScoreWindowResult,
6
10
  CactusLMEmbedParams,
7
11
  CactusLMEmbedResult,
8
12
  CactusLMImageEmbedParams,
@@ -46,6 +50,11 @@ export class CactusLM {
46
50
  public async download({
47
51
  onProgress,
48
52
  }: CactusLMDownloadParams = {}): Promise<void> {
53
+ if (this.isModelPath(this.model)) {
54
+ onProgress?.(1.0);
55
+ return;
56
+ }
57
+
49
58
  if (this.isDownloading) {
50
59
  throw new Error('CactusLM is already downloading');
51
60
  }
@@ -73,12 +82,16 @@ export class CactusLM {
73
82
  return;
74
83
  }
75
84
 
76
- if (!(await CactusFileSystem.modelExists(this.model))) {
77
- throw new Error(`Model "${this.model}" is not downloaded`);
85
+ let modelPath: string;
86
+ if (this.isModelPath(this.model)) {
87
+ modelPath = this.model.replace('file://', '');
88
+ } else {
89
+ if (!(await CactusFileSystem.modelExists(this.model))) {
90
+ throw new Error(`Model "${this.model}" is not downloaded`);
91
+ }
92
+ modelPath = await CactusFileSystem.getModelPath(this.model);
78
93
  }
79
94
 
80
- const modelPath = await CactusFileSystem.getModelPath(this.model);
81
-
82
95
  try {
83
96
  await this.cactus.init(modelPath, this.contextSize, this.corpusDir);
84
97
  Telemetry.logInit(this.model, true);
@@ -153,8 +166,26 @@ export class CactusLM {
153
166
  }
154
167
  }
155
168
 
169
+ public async tokenize({
170
+ text,
171
+ }: CactusLMTokenizeParams): Promise<CactusLMTokenizeResult> {
172
+ return { tokens: await this.cactus.tokenize(text) };
173
+ }
174
+
175
+ public async scoreWindow({
176
+ tokens,
177
+ start,
178
+ end,
179
+ context,
180
+ }: CactusLMScoreWindowParams): Promise<CactusLMScoreWindowResult> {
181
+ return {
182
+ score: await this.cactus.scoreWindow(tokens, start, end, context),
183
+ };
184
+ }
185
+
156
186
  public async embed({
157
187
  text,
188
+ normalize = false,
158
189
  }: CactusLMEmbedParams): Promise<CactusLMEmbedResult> {
159
190
  if (this.isGenerating) {
160
191
  throw new Error('CactusLM is already generating');
@@ -166,7 +197,8 @@ export class CactusLM {
166
197
  try {
167
198
  const embedding = await this.cactus.embed(
168
199
  text,
169
- CactusLM.defaultEmbedBufferSize
200
+ CactusLM.defaultEmbedBufferSize,
201
+ normalize
170
202
  );
171
203
  Telemetry.logEmbedding(this.model, true);
172
204
  return { embedding };
@@ -230,4 +262,8 @@ export class CactusLM {
230
262
  }
231
263
  return models;
232
264
  }
265
+
266
+ private isModelPath(model: string): boolean {
267
+ return model.startsWith('file://') || model.startsWith('/');
268
+ }
233
269
  }
@@ -42,6 +42,11 @@ export class CactusSTT {
42
42
  public async download({
43
43
  onProgress,
44
44
  }: CactusSTTDownloadParams = {}): Promise<void> {
45
+ if (this.isModelPath(this.model)) {
46
+ onProgress?.(1.0);
47
+ return;
48
+ }
49
+
45
50
  if (this.isDownloading) {
46
51
  throw new Error('CactusSTT is already downloading');
47
52
  }
@@ -69,12 +74,16 @@ export class CactusSTT {
69
74
  return;
70
75
  }
71
76
 
72
- if (!(await CactusFileSystem.modelExists(this.model))) {
73
- throw new Error(`Model "${this.model}" is not downloaded`);
77
+ let modelPath: string;
78
+ if (this.isModelPath(this.model)) {
79
+ modelPath = this.model.replace('file://', '');
80
+ } else {
81
+ if (!(await CactusFileSystem.modelExists(this.model))) {
82
+ throw new Error(`Model "${this.model}" is not downloaded`);
83
+ }
84
+ modelPath = await CactusFileSystem.getModelPath(this.model);
74
85
  }
75
86
 
76
- const modelPath = await CactusFileSystem.getModelPath(this.model);
77
-
78
87
  try {
79
88
  await this.cactus.init(modelPath, this.contextSize);
80
89
  Telemetry.logInit(this.model, true);
@@ -86,7 +95,7 @@ export class CactusSTT {
86
95
  }
87
96
 
88
97
  public async transcribe({
89
- audioFilePath,
98
+ audio,
90
99
  prompt,
91
100
  options,
92
101
  onToken,
@@ -107,7 +116,7 @@ export class CactusSTT {
107
116
  this.isGenerating = true;
108
117
  try {
109
118
  const result = await this.cactus.transcribe(
110
- audioFilePath,
119
+ audio,
111
120
  prompt,
112
121
  responseBufferSize,
113
122
  options,
@@ -180,4 +189,8 @@ export class CactusSTT {
180
189
  }
181
190
  return models;
182
191
  }
192
+
193
+ private isModelPath(model: string): boolean {
194
+ return model.startsWith('file://') || model.startsWith('/');
195
+ }
183
196
  }
@@ -5,4 +5,7 @@ export class CactusConfig {
5
5
 
6
6
  // Hybrid mode
7
7
  public static cactusToken?: string;
8
+
9
+ // Pro features
10
+ public static cactusProKey?: string;
8
11
  }
@@ -1 +1 @@
1
- export const packageVersion = '1.2.1';
1
+ export const packageVersion = '1.4.0';
@@ -0,0 +1,195 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { CactusIndex } from '../classes/CactusIndex';
3
+ import { getErrorMessage } from '../utils/error';
4
+ import type {
5
+ CactusIndexParams,
6
+ CactusIndexAddParams,
7
+ CactusIndexGetParams,
8
+ CactusIndexGetResult,
9
+ CactusIndexQueryParams,
10
+ CactusIndexQueryResult,
11
+ CactusIndexDeleteParams,
12
+ } from '../types/CactusIndex';
13
+
14
+ export const useCactusIndex = ({ name, embeddingDim }: CactusIndexParams) => {
15
+ const [cactusIndex, setCactusIndex] = useState(
16
+ () => new CactusIndex(name, embeddingDim)
17
+ );
18
+
19
+ // State
20
+ const [isInitializing, setIsInitializing] = useState(false);
21
+ const [isProcessing, setIsProcessing] = useState(false);
22
+ const [error, setError] = useState<string | null>(null);
23
+
24
+ useEffect(() => {
25
+ setCactusIndex(new CactusIndex(name, embeddingDim));
26
+
27
+ setIsInitializing(false);
28
+ setIsProcessing(false);
29
+ setError(null);
30
+ }, [name, embeddingDim]);
31
+
32
+ useEffect(() => {
33
+ return () => {
34
+ cactusIndex.destroy().catch(() => {});
35
+ };
36
+ }, [cactusIndex]);
37
+
38
+ const init = useCallback(async () => {
39
+ if (isInitializing) {
40
+ const message = 'CactusIndex is already initializing';
41
+ setError(message);
42
+ throw new Error(message);
43
+ }
44
+
45
+ setError(null);
46
+ setIsInitializing(true);
47
+ try {
48
+ await cactusIndex.init();
49
+ } catch (e) {
50
+ setError(getErrorMessage(e));
51
+ throw e;
52
+ } finally {
53
+ setIsInitializing(false);
54
+ }
55
+ }, [cactusIndex, isInitializing]);
56
+
57
+ const add = useCallback(
58
+ async ({
59
+ ids,
60
+ documents,
61
+ metadatas,
62
+ embeddings,
63
+ }: CactusIndexAddParams): Promise<void> => {
64
+ if (isProcessing) {
65
+ const message = 'CactusIndex is already processing';
66
+ setError(message);
67
+ throw new Error(message);
68
+ }
69
+
70
+ setError(null);
71
+ setIsProcessing(true);
72
+ try {
73
+ await cactusIndex.add({ ids, documents, metadatas, embeddings });
74
+ } catch (e) {
75
+ setError(getErrorMessage(e));
76
+ throw e;
77
+ } finally {
78
+ setIsProcessing(false);
79
+ }
80
+ },
81
+ [cactusIndex, isProcessing]
82
+ );
83
+
84
+ const _delete = useCallback(
85
+ async ({ ids }: CactusIndexDeleteParams): Promise<void> => {
86
+ if (isProcessing) {
87
+ const message = 'CactusIndex is already processing';
88
+ setError(message);
89
+ throw new Error(message);
90
+ }
91
+
92
+ setError(null);
93
+ setIsProcessing(true);
94
+ try {
95
+ await cactusIndex.delete({ ids });
96
+ } catch (e) {
97
+ setError(getErrorMessage(e));
98
+ throw e;
99
+ } finally {
100
+ setIsProcessing(false);
101
+ }
102
+ },
103
+ [cactusIndex, isProcessing]
104
+ );
105
+
106
+ const get = useCallback(
107
+ async ({ ids }: CactusIndexGetParams): Promise<CactusIndexGetResult> => {
108
+ if (isProcessing) {
109
+ const message = 'CactusIndex is already processing';
110
+ setError(message);
111
+ throw new Error(message);
112
+ }
113
+
114
+ setError(null);
115
+ setIsProcessing(true);
116
+ try {
117
+ return await cactusIndex.get({ ids });
118
+ } catch (e) {
119
+ setError(getErrorMessage(e));
120
+ throw e;
121
+ } finally {
122
+ setIsProcessing(false);
123
+ }
124
+ },
125
+ [cactusIndex, isProcessing]
126
+ );
127
+
128
+ const query = useCallback(
129
+ async ({
130
+ embeddings,
131
+ options,
132
+ }: CactusIndexQueryParams): Promise<CactusIndexQueryResult> => {
133
+ if (isProcessing) {
134
+ const message = 'CactusIndex is already processing';
135
+ setError(message);
136
+ throw new Error(message);
137
+ }
138
+
139
+ setError(null);
140
+ setIsProcessing(true);
141
+ try {
142
+ return await cactusIndex.query({ embeddings, options });
143
+ } catch (e) {
144
+ setError(getErrorMessage(e));
145
+ throw e;
146
+ } finally {
147
+ setIsProcessing(false);
148
+ }
149
+ },
150
+ [cactusIndex, isProcessing]
151
+ );
152
+
153
+ const compact = useCallback(async () => {
154
+ if (isProcessing) {
155
+ const message = 'CactusIndex is already processing';
156
+ setError(message);
157
+ throw new Error(message);
158
+ }
159
+
160
+ setError(null);
161
+ setIsProcessing(true);
162
+ try {
163
+ await cactusIndex.compact();
164
+ } catch (e) {
165
+ setError(getErrorMessage(e));
166
+ throw e;
167
+ } finally {
168
+ setIsProcessing(false);
169
+ }
170
+ }, [cactusIndex, isProcessing]);
171
+
172
+ const destroy = useCallback(async () => {
173
+ setError(null);
174
+ try {
175
+ await cactusIndex.destroy();
176
+ } catch (e) {
177
+ setError(getErrorMessage(e));
178
+ throw e;
179
+ }
180
+ }, [cactusIndex]);
181
+
182
+ return {
183
+ isInitializing,
184
+ isProcessing,
185
+ error,
186
+
187
+ init,
188
+ add,
189
+ delete: _delete,
190
+ get,
191
+ query,
192
+ compact,
193
+ destroy,
194
+ };
195
+ };