cactus-react-native 1.2.0 → 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 (222) hide show
  1. package/README.md +573 -13
  2. package/android/CMakeLists.txt +4 -3
  3. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusFileSystem.kt +21 -4
  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 +57 -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 -10
  49. package/lib/module/classes/CactusLM.js.map +1 -1
  50. package/lib/module/classes/CactusSTT.js +20 -12
  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 +21 -5
  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/module/types/CactusSTTModel.js +2 -0
  80. package/lib/module/types/CactusSTTModel.js.map +1 -0
  81. package/lib/typescript/src/api/Database.d.ts +7 -1
  82. package/lib/typescript/src/api/Database.d.ts.map +1 -1
  83. package/lib/typescript/src/classes/CactusIndex.d.ts +15 -0
  84. package/lib/typescript/src/classes/CactusIndex.d.ts.map +1 -0
  85. package/lib/typescript/src/classes/CactusLM.d.ts +5 -3
  86. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  87. package/lib/typescript/src/classes/CactusSTT.d.ts +4 -4
  88. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  89. package/lib/typescript/src/config/CactusConfig.d.ts +1 -0
  90. package/lib/typescript/src/config/CactusConfig.d.ts.map +1 -1
  91. package/lib/typescript/src/constants/packageVersion.d.ts +1 -1
  92. package/lib/typescript/src/hooks/useCactusIndex.d.ts +14 -0
  93. package/lib/typescript/src/hooks/useCactusIndex.d.ts.map +1 -0
  94. package/lib/typescript/src/hooks/useCactusLM.d.ts +4 -2
  95. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  96. package/lib/typescript/src/hooks/useCactusSTT.d.ts +3 -3
  97. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  98. package/lib/typescript/src/index.d.ts +5 -1
  99. package/lib/typescript/src/index.d.ts.map +1 -1
  100. package/lib/typescript/src/native/Cactus.d.ts +4 -2
  101. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  102. package/lib/typescript/src/native/CactusFileSystem.d.ts +1 -0
  103. package/lib/typescript/src/native/CactusFileSystem.d.ts.map +1 -1
  104. package/lib/typescript/src/native/CactusIndex.d.ts +12 -0
  105. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -0
  106. package/lib/typescript/src/native/CactusUtil.d.ts.map +1 -1
  107. package/lib/typescript/src/native/index.d.ts +1 -0
  108. package/lib/typescript/src/native/index.d.ts.map +1 -1
  109. package/lib/typescript/src/specs/Cactus.nitro.d.ts +4 -2
  110. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  111. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts +1 -0
  112. package/lib/typescript/src/specs/CactusFileSystem.nitro.d.ts.map +1 -1
  113. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts +24 -0
  114. package/lib/typescript/src/specs/CactusIndex.nitro.d.ts.map +1 -0
  115. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts +1 -1
  116. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts.map +1 -1
  117. package/lib/typescript/src/types/CactusIndex.d.ts +34 -0
  118. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -0
  119. package/lib/typescript/src/types/CactusLM.d.ts +17 -0
  120. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  121. package/lib/typescript/src/types/CactusModel.d.ts +1 -0
  122. package/lib/typescript/src/types/CactusModel.d.ts.map +1 -1
  123. package/lib/typescript/src/types/CactusSTT.d.ts +1 -1
  124. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  125. package/lib/typescript/src/types/CactusSTTModel.d.ts +8 -0
  126. package/lib/typescript/src/types/CactusSTTModel.d.ts.map +1 -0
  127. package/nitro.json +3 -0
  128. package/nitrogen/generated/android/c++/JDeviceInfo.hpp +1 -1
  129. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +1 -1
  130. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +1 -1
  131. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +1 -1
  132. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +1 -1
  133. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +1 -1
  134. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.cpp +17 -1
  135. package/nitrogen/generated/android/c++/JHybridCactusFileSystemSpec.hpp +2 -1
  136. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.cpp +1 -1
  137. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.hpp +1 -1
  138. package/nitrogen/generated/android/cactus+autolinking.cmake +2 -1
  139. package/nitrogen/generated/android/cactus+autolinking.gradle +1 -1
  140. package/nitrogen/generated/android/cactusOnLoad.cpp +11 -1
  141. package/nitrogen/generated/android/cactusOnLoad.hpp +1 -1
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +1 -1
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/Func_void_double.kt +1 -1
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +1 -1
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +1 -1
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusFileSystemSpec.kt +5 -1
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusImageSpec.kt +1 -1
  148. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/cactusOnLoad.kt +1 -1
  149. package/nitrogen/generated/ios/Cactus+autolinking.rb +1 -1
  150. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +1 -1
  151. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +1 -1
  152. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +1 -1
  153. package/nitrogen/generated/ios/CactusAutolinking.mm +11 -1
  154. package/nitrogen/generated/ios/CactusAutolinking.swift +1 -1
  155. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +1 -1
  156. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +1 -1
  157. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +1 -1
  158. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +1 -1
  159. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.cpp +1 -1
  160. package/nitrogen/generated/ios/c++/HybridCactusFileSystemSpecSwift.hpp +9 -1
  161. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.cpp +1 -1
  162. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.hpp +1 -1
  163. package/nitrogen/generated/ios/swift/DeviceInfo.swift +1 -1
  164. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  165. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +1 -1
  166. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -1
  167. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -1
  168. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -1
  169. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +1 -1
  170. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -1
  171. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +1 -1
  172. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +1 -1
  173. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +1 -1
  174. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +1 -1
  175. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec.swift +2 -1
  176. package/nitrogen/generated/ios/swift/HybridCactusFileSystemSpec_cxx.swift +20 -1
  177. package/nitrogen/generated/ios/swift/HybridCactusImageSpec.swift +1 -1
  178. package/nitrogen/generated/ios/swift/HybridCactusImageSpec_cxx.swift +1 -1
  179. package/nitrogen/generated/shared/c++/CactusIndexGetResult.hpp +84 -0
  180. package/nitrogen/generated/shared/c++/CactusIndexQueryResult.hpp +79 -0
  181. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +1 -1
  182. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +1 -1
  183. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +1 -1
  184. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +1 -1
  185. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +1 -1
  186. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.cpp +2 -1
  187. package/nitrogen/generated/shared/c++/HybridCactusFileSystemSpec.hpp +2 -1
  188. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.cpp +1 -1
  189. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.hpp +1 -1
  190. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.cpp +27 -0
  191. package/nitrogen/generated/shared/c++/HybridCactusIndexSpec.hpp +76 -0
  192. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +3 -1
  193. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +6 -3
  194. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +1 -1
  195. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +2 -2
  196. package/package.json +2 -2
  197. package/src/api/Database.ts +80 -2
  198. package/src/classes/CactusIndex.ts +58 -0
  199. package/src/classes/CactusLM.ts +41 -11
  200. package/src/classes/CactusSTT.ts +24 -16
  201. package/src/config/CactusConfig.ts +3 -0
  202. package/src/constants/packageVersion.ts +1 -1
  203. package/src/hooks/useCactusIndex.ts +195 -0
  204. package/src/hooks/useCactusLM.ts +63 -3
  205. package/src/hooks/useCactusSTT.ts +4 -4
  206. package/src/index.tsx +17 -0
  207. package/src/native/Cactus.ts +39 -4
  208. package/src/native/CactusFileSystem.ts +4 -0
  209. package/src/native/CactusIndex.ts +54 -0
  210. package/src/native/CactusUtil.ts +19 -3
  211. package/src/native/index.ts +1 -0
  212. package/src/specs/Cactus.nitro.ts +13 -2
  213. package/src/specs/CactusFileSystem.nitro.ts +2 -0
  214. package/src/specs/CactusIndex.nitro.ts +31 -0
  215. package/src/specs/CactusUtil.nitro.ts +1 -1
  216. package/src/telemetry/Telemetry.ts +1 -1
  217. package/src/types/CactusIndex.ts +40 -0
  218. package/src/types/CactusLM.ts +21 -0
  219. package/src/types/CactusModel.ts +1 -0
  220. package/src/types/CactusSTT.ts +1 -1
  221. package/src/types/CactusSTTModel.ts +10 -0
  222. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.so +0 -0
@@ -7,11 +7,11 @@ import type {
7
7
  CactusSTTAudioEmbedParams,
8
8
  CactusSTTAudioEmbedResult,
9
9
  } from '../types/CactusSTT';
10
- import type { CactusModel } from '../types/CactusModel';
11
10
  import { Telemetry } from '../telemetry/Telemetry';
12
11
  import { CactusConfig } from '../config/CactusConfig';
13
12
  import { Database } from '../api/Database';
14
13
  import { getErrorMessage } from '../utils/error';
14
+ import type { CactusSTTModel } from '../types/CactusSTTModel';
15
15
 
16
16
  export class CactusSTT {
17
17
  private readonly cactus = new Cactus();
@@ -32,8 +32,6 @@ export class CactusSTT {
32
32
  };
33
33
  private static readonly defaultEmbedBufferSize = 4096;
34
34
 
35
- private static cactusModelsCache: CactusModel[] | null = null;
36
-
37
35
  constructor({ model, contextSize }: CactusSTTParams = {}) {
38
36
  Telemetry.init(CactusConfig.telemetryToken);
39
37
 
@@ -44,6 +42,11 @@ export class CactusSTT {
44
42
  public async download({
45
43
  onProgress,
46
44
  }: CactusSTTDownloadParams = {}): Promise<void> {
45
+ if (this.isModelPath(this.model)) {
46
+ onProgress?.(1.0);
47
+ return;
48
+ }
49
+
47
50
  if (this.isDownloading) {
48
51
  throw new Error('CactusSTT is already downloading');
49
52
  }
@@ -55,9 +58,10 @@ export class CactusSTT {
55
58
 
56
59
  this.isDownloading = true;
57
60
  try {
61
+ const model = await Database.getSTTModel(this.model);
58
62
  await CactusFileSystem.downloadModel(
59
63
  this.model,
60
- `https://vlqqczxwyaodtcdmdmlw.supabase.co/storage/v1/object/public/voice-models/${this.model}.zip`,
64
+ model.downloadUrl,
61
65
  onProgress
62
66
  );
63
67
  } finally {
@@ -70,12 +74,16 @@ export class CactusSTT {
70
74
  return;
71
75
  }
72
76
 
73
- if (!(await CactusFileSystem.modelExists(this.model))) {
74
- 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);
75
85
  }
76
86
 
77
- const modelPath = await CactusFileSystem.getModelPath(this.model);
78
-
79
87
  try {
80
88
  await this.cactus.init(modelPath, this.contextSize);
81
89
  Telemetry.logInit(this.model, true);
@@ -87,7 +95,7 @@ export class CactusSTT {
87
95
  }
88
96
 
89
97
  public async transcribe({
90
- audioFilePath,
98
+ audio,
91
99
  prompt,
92
100
  options,
93
101
  onToken,
@@ -108,7 +116,7 @@ export class CactusSTT {
108
116
  this.isGenerating = true;
109
117
  try {
110
118
  const result = await this.cactus.transcribe(
111
- audioFilePath,
119
+ audio,
112
120
  prompt,
113
121
  responseBufferSize,
114
122
  options,
@@ -174,15 +182,15 @@ export class CactusSTT {
174
182
  this.isInitialized = false;
175
183
  }
176
184
 
177
- public async getModels(): Promise<CactusModel[]> {
178
- if (CactusSTT.cactusModelsCache) {
179
- return CactusSTT.cactusModelsCache;
180
- }
181
- const models = await Database.getModels();
185
+ public async getModels(): Promise<CactusSTTModel[]> {
186
+ const models = await Database.getSTTModels();
182
187
  for (const model of models) {
183
188
  model.isDownloaded = await CactusFileSystem.modelExists(model.slug);
184
189
  }
185
- CactusSTT.cactusModelsCache = models;
186
190
  return models;
187
191
  }
192
+
193
+ private isModelPath(model: string): boolean {
194
+ return model.startsWith('file://') || model.startsWith('/');
195
+ }
188
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.0';
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
+ };
@@ -4,12 +4,16 @@ import { CactusFileSystem } from '../native';
4
4
  import { getErrorMessage } from '../utils/error';
5
5
  import type {
6
6
  CactusLMParams,
7
+ CactusLMCompleteParams,
7
8
  CactusLMCompleteResult,
9
+ CactusLMTokenizeParams,
10
+ CactusLMTokenizeResult,
11
+ CactusLMScoreWindowParams,
12
+ CactusLMScoreWindowResult,
8
13
  CactusLMEmbedParams,
9
14
  CactusLMEmbedResult,
10
15
  CactusLMImageEmbedParams,
11
16
  CactusLMImageEmbedResult,
12
- CactusLMCompleteParams,
13
17
  CactusLMDownloadParams,
14
18
  } from '../types/CactusLM';
15
19
  import type { CactusModel } from '../types/CactusModel';
@@ -201,8 +205,62 @@ export const useCactusLM = ({
201
205
  [cactusLM, isGenerating]
202
206
  );
203
207
 
208
+ const tokenize = useCallback(
209
+ async ({
210
+ text,
211
+ }: CactusLMTokenizeParams): Promise<CactusLMTokenizeResult> => {
212
+ if (isGenerating) {
213
+ const message = 'CactusLM is already generating';
214
+ setError(message);
215
+ throw new Error(message);
216
+ }
217
+
218
+ setError(null);
219
+ setIsGenerating(true);
220
+ try {
221
+ return await cactusLM.tokenize({ text });
222
+ } catch (e) {
223
+ setError(getErrorMessage(e));
224
+ throw e;
225
+ } finally {
226
+ setIsGenerating(false);
227
+ }
228
+ },
229
+ [cactusLM, isGenerating]
230
+ );
231
+
232
+ const scoreWindow = useCallback(
233
+ async ({
234
+ tokens,
235
+ start,
236
+ end,
237
+ context,
238
+ }: CactusLMScoreWindowParams): Promise<CactusLMScoreWindowResult> => {
239
+ if (isGenerating) {
240
+ const message = 'CactusLM is already generating';
241
+ setError(message);
242
+ throw new Error(message);
243
+ }
244
+
245
+ setError(null);
246
+ setIsGenerating(true);
247
+ try {
248
+ return await cactusLM.scoreWindow({ tokens, start, end, context });
249
+ } catch (e) {
250
+ setError(getErrorMessage(e));
251
+ throw e;
252
+ } finally {
253
+ setIsGenerating(false);
254
+ }
255
+ },
256
+ [cactusLM, isGenerating]
257
+ );
258
+
204
259
  const embed = useCallback(
205
- async ({ text }: CactusLMEmbedParams): Promise<CactusLMEmbedResult> => {
260
+ async ({
261
+ text,
262
+ normalize = false,
263
+ }: CactusLMEmbedParams): Promise<CactusLMEmbedResult> => {
206
264
  if (isGenerating) {
207
265
  const message = 'CactusLM is already generating';
208
266
  setError(message);
@@ -212,7 +270,7 @@ export const useCactusLM = ({
212
270
  setError(null);
213
271
  setIsGenerating(true);
214
272
  try {
215
- return await cactusLM.embed({ text });
273
+ return await cactusLM.embed({ text, normalize });
216
274
  } catch (e) {
217
275
  setError(getErrorMessage(e));
218
276
  throw e;
@@ -303,6 +361,8 @@ export const useCactusLM = ({
303
361
  download,
304
362
  init,
305
363
  complete,
364
+ tokenize,
365
+ scoreWindow,
306
366
  embed,
307
367
  imageEmbed,
308
368
  reset,
@@ -10,7 +10,7 @@ import type {
10
10
  CactusSTTAudioEmbedParams,
11
11
  CactusSTTAudioEmbedResult,
12
12
  } from '../types/CactusSTT';
13
- import type { CactusModel } from '../types/CactusModel';
13
+ import type { CactusSTTModel } from '../types/CactusSTTModel';
14
14
 
15
15
  export const useCactusSTT = ({
16
16
  model = 'whisper-small',
@@ -162,7 +162,7 @@ export const useCactusSTT = ({
162
162
 
163
163
  const transcribe = useCallback(
164
164
  async ({
165
- audioFilePath,
165
+ audio,
166
166
  prompt,
167
167
  options,
168
168
  onToken,
@@ -178,7 +178,7 @@ export const useCactusSTT = ({
178
178
  setIsGenerating(true);
179
179
  try {
180
180
  return await cactusSTT.transcribe({
181
- audioFilePath,
181
+ audio,
182
182
  prompt,
183
183
  options,
184
184
  onToken: (token) => {
@@ -254,7 +254,7 @@ export const useCactusSTT = ({
254
254
  }
255
255
  }, [cactusSTT]);
256
256
 
257
- const getModels = useCallback(async (): Promise<CactusModel[]> => {
257
+ const getModels = useCallback(async (): Promise<CactusSTTModel[]> => {
258
258
  setError(null);
259
259
  try {
260
260
  return await cactusSTT.getModels();
package/src/index.tsx CHANGED
@@ -1,13 +1,16 @@
1
1
  // Classes
2
2
  export { CactusLM } from './classes/CactusLM';
3
3
  export { CactusSTT } from './classes/CactusSTT';
4
+ export { CactusIndex } from './classes/CactusIndex';
4
5
 
5
6
  // Hooks
6
7
  export { useCactusLM } from './hooks/useCactusLM';
7
8
  export { useCactusSTT } from './hooks/useCactusSTT';
9
+ export { useCactusIndex } from './hooks/useCactusIndex';
8
10
 
9
11
  // Types
10
12
  export type { CactusModel } from './types/CactusModel';
13
+ export type { CactusSTTModel } from './types/CactusSTTModel';
11
14
  export type {
12
15
  CactusLMParams,
13
16
  CactusLMDownloadParams,
@@ -16,6 +19,10 @@ export type {
16
19
  Tool,
17
20
  CactusLMCompleteParams,
18
21
  CactusLMCompleteResult,
22
+ CactusLMTokenizeParams,
23
+ CactusLMTokenizeResult,
24
+ CactusLMScoreWindowParams,
25
+ CactusLMScoreWindowResult,
19
26
  CactusLMEmbedParams,
20
27
  CactusLMEmbedResult,
21
28
  CactusLMImageEmbedParams,
@@ -30,6 +37,16 @@ export type {
30
37
  CactusSTTAudioEmbedParams,
31
38
  CactusSTTAudioEmbedResult,
32
39
  } from './types/CactusSTT';
40
+ export type {
41
+ CactusIndexParams,
42
+ CactusIndexAddParams,
43
+ CactusIndexGetParams,
44
+ CactusIndexGetResult,
45
+ IndexQueryOptions,
46
+ CactusIndexQueryParams,
47
+ CactusIndexQueryResult,
48
+ CactusIndexDeleteParams,
49
+ } from './types/CactusIndex';
33
50
 
34
51
  // Config
35
52
  export { CactusConfig } from './config/CactusConfig';
@@ -37,6 +37,7 @@ export class Cactus {
37
37
  messagesInternal.push(message);
38
38
  continue;
39
39
  }
40
+
40
41
  const resizedImages: string[] = [];
41
42
  for (const imagePath of message.images) {
42
43
  const resizedImage = await CactusImage.resize(
@@ -47,6 +48,7 @@ export class Cactus {
47
48
  );
48
49
  resizedImages.push(resizedImage);
49
50
  }
51
+
50
52
  messagesInternal.push({ ...message, images: resizedImages });
51
53
  }
52
54
 
@@ -58,6 +60,7 @@ export class Cactus {
58
60
  top_k: options.topK,
59
61
  max_tokens: options.maxTokens,
60
62
  stop_sequences: options.stopSequences,
63
+ force_tools: options.forceTools,
61
64
  })
62
65
  : undefined;
63
66
  const toolsJson = JSON.stringify(tools);
@@ -89,13 +92,41 @@ export class Cactus {
89
92
  }
90
93
  }
91
94
 
95
+ public tokenize(text: string): Promise<number[]> {
96
+ return this.hybridCactus.tokenize(text);
97
+ }
98
+
99
+ public async scoreWindow(
100
+ tokens: number[],
101
+ start: number,
102
+ end: number,
103
+ context: number
104
+ ): Promise<number> {
105
+ const response = await this.hybridCactus.scoreWindow(
106
+ tokens,
107
+ start,
108
+ end,
109
+ context
110
+ );
111
+ try {
112
+ const parsed = JSON.parse(response);
113
+ return parsed.logprob;
114
+ } catch {
115
+ throw new Error('Unable to parse score window response');
116
+ }
117
+ }
118
+
92
119
  public async transcribe(
93
- audioFilePath: string,
120
+ audio: string | number[],
94
121
  prompt: string,
95
122
  responseBufferSize: number,
96
123
  options?: TranscribeOptions,
97
124
  callback?: (token: string, tokenId: number) => void
98
125
  ): Promise<CactusSTTTranscribeResult> {
126
+ if (typeof audio === 'string') {
127
+ audio = audio.replace('file://', '');
128
+ }
129
+
99
130
  const optionsJson = options
100
131
  ? JSON.stringify({
101
132
  temperature: options.temperature,
@@ -107,7 +138,7 @@ export class Cactus {
107
138
  : undefined;
108
139
 
109
140
  const response = await this.hybridCactus.transcribe(
110
- audioFilePath.replace('file://', ''),
141
+ audio,
111
142
  prompt,
112
143
  responseBufferSize,
113
144
  optionsJson,
@@ -132,8 +163,12 @@ export class Cactus {
132
163
  }
133
164
  }
134
165
 
135
- public embed(text: string, embeddingBufferSize: number): Promise<number[]> {
136
- return this.hybridCactus.embed(text, embeddingBufferSize);
166
+ public embed(
167
+ text: string,
168
+ embeddingBufferSize: number,
169
+ normalize: boolean
170
+ ): Promise<number[]> {
171
+ return this.hybridCactus.embed(text, embeddingBufferSize, normalize);
137
172
  }
138
173
 
139
174
  public async imageEmbed(
@@ -33,6 +33,10 @@ export class CactusFileSystem {
33
33
  return this.hybridCactusFileSystem.getModelPath(model);
34
34
  }
35
35
 
36
+ public static getIndexPath(name: string): Promise<string> {
37
+ return this.hybridCactusFileSystem.getIndexPath(name);
38
+ }
39
+
36
40
  public static downloadModel(
37
41
  model: string,
38
42
  url: string,
@@ -0,0 +1,54 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ import type { CactusIndex as CactusIndexSpec } from '../specs/CactusIndex.nitro';
3
+ import type {
4
+ CactusIndexGetResult,
5
+ CactusIndexQueryResult,
6
+ IndexQueryOptions,
7
+ } from '../types/CactusIndex';
8
+
9
+ export class CactusIndex {
10
+ private readonly hybridCactusIndex =
11
+ NitroModules.createHybridObject<CactusIndexSpec>('CactusIndex');
12
+
13
+ public init(indexPath: string, embeddingDim: number): Promise<void> {
14
+ return this.hybridCactusIndex.init(indexPath, embeddingDim);
15
+ }
16
+
17
+ public add(
18
+ ids: number[],
19
+ documents: string[],
20
+ embeddings: number[][],
21
+ metadatas?: string[]
22
+ ): Promise<void> {
23
+ return this.hybridCactusIndex.add(ids, documents, embeddings, metadatas);
24
+ }
25
+
26
+ public delete(ids: number[]): Promise<void> {
27
+ return this.hybridCactusIndex._delete(ids);
28
+ }
29
+
30
+ public get(ids: number[]): Promise<CactusIndexGetResult> {
31
+ return this.hybridCactusIndex.get(ids);
32
+ }
33
+
34
+ public query(
35
+ embeddings: number[][],
36
+ options?: IndexQueryOptions
37
+ ): Promise<CactusIndexQueryResult> {
38
+ const optionsJson = options
39
+ ? JSON.stringify({
40
+ top_k: options.topK,
41
+ score_threshold: options.scoreThreshold,
42
+ })
43
+ : undefined;
44
+ return this.hybridCactusIndex.query(embeddings, optionsJson);
45
+ }
46
+
47
+ public compact(): Promise<void> {
48
+ return this.hybridCactusIndex.compact();
49
+ }
50
+
51
+ public destroy(): Promise<void> {
52
+ return this.hybridCactusIndex.destroy();
53
+ }
54
+ }
@@ -2,6 +2,8 @@ import { NitroModules } from 'react-native-nitro-modules';
2
2
  import type { CactusUtil as CactusUtilSpec } from '../specs/CactusUtil.nitro';
3
3
  import { Platform } from 'react-native';
4
4
  import { CactusFileSystem } from './CactusFileSystem';
5
+ import { CactusConfig } from '../config/CactusConfig';
6
+ import { Database } from '../api/Database';
5
7
 
6
8
  export class CactusUtil {
7
9
  private static readonly hybridCactusUtil =
@@ -10,7 +12,7 @@ export class CactusUtil {
10
12
  public static async registerApp(encryptedData: string): Promise<string> {
11
13
  if (Platform.OS === 'android') {
12
14
  const cactusDirectory = await CactusFileSystem.getCactusDirectory();
13
- this.hybridCactusUtil.setAndroidDataDirectory(cactusDirectory);
15
+ await this.hybridCactusUtil.setAndroidDataDirectory(cactusDirectory);
14
16
  }
15
17
 
16
18
  return this.hybridCactusUtil.registerApp(encryptedData);
@@ -19,9 +21,23 @@ export class CactusUtil {
19
21
  public static async getDeviceId(): Promise<string | null> {
20
22
  if (Platform.OS === 'android') {
21
23
  const cactusDirectory = await CactusFileSystem.getCactusDirectory();
22
- this.hybridCactusUtil.setAndroidDataDirectory(cactusDirectory);
24
+ await this.hybridCactusUtil.setAndroidDataDirectory(cactusDirectory);
23
25
  }
24
26
 
25
- return this.hybridCactusUtil.getDeviceId();
27
+ const deviceId = await this.hybridCactusUtil.getDeviceId(
28
+ CactusConfig.cactusProKey
29
+ );
30
+
31
+ if (!deviceId) {
32
+ return null;
33
+ }
34
+
35
+ if (deviceId?.indexOf('|') !== -1) {
36
+ const parts = deviceId.split('|');
37
+ CactusConfig.cactusProKey = parts[1];
38
+ return await Database.registerDevice({ deviceId: parts[0] });
39
+ }
40
+
41
+ return deviceId;
26
42
  }
27
43
  }
@@ -1,4 +1,5 @@
1
1
  export { Cactus } from './Cactus';
2
+ export { CactusIndex } from './CactusIndex';
2
3
  export { CactusCrypto } from './CactusCrypto';
3
4
  export { CactusDeviceInfo } from './CactusDeviceInfo';
4
5
  export { CactusFileSystem } from './CactusFileSystem';