cactus-react-native 1.4.0 → 1.7.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 (226) hide show
  1. package/Cactus.podspec +1 -1
  2. package/README.md +465 -174
  3. package/android/CMakeLists.txt +24 -5
  4. package/android/src/main/jniLibs/arm64-v8a/libcactus.a +0 -0
  5. package/android/src/main/jniLibs/arm64-v8a/libcurl.a +0 -0
  6. package/android/src/main/jniLibs/arm64-v8a/libmbedcrypto.a +0 -0
  7. package/android/src/main/jniLibs/arm64-v8a/libmbedtls.a +0 -0
  8. package/android/src/main/jniLibs/arm64-v8a/libmbedx509.a +0 -0
  9. package/cpp/HybridCactus.cpp +157 -6
  10. package/cpp/HybridCactus.hpp +20 -3
  11. package/cpp/cactus_ffi.h +65 -30
  12. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus.h +0 -1
  13. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_ffi.h +65 -30
  14. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_utils.h +357 -122
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +184 -63
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/gemma_tools.h +549 -0
  17. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +153 -27
  18. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +90 -178
  19. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel_utils.h +276 -151
  20. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  21. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus.h +0 -1
  22. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +65 -30
  23. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_utils.h +357 -122
  24. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +184 -63
  25. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/gemma_tools.h +549 -0
  26. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +153 -27
  27. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +90 -178
  28. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel_utils.h +276 -151
  29. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  30. package/lib/module/classes/CactusLM.js +43 -58
  31. package/lib/module/classes/CactusLM.js.map +1 -1
  32. package/lib/module/classes/CactusSTT.js +64 -38
  33. package/lib/module/classes/CactusSTT.js.map +1 -1
  34. package/lib/module/classes/CactusVAD.js +95 -0
  35. package/lib/module/classes/CactusVAD.js.map +1 -0
  36. package/lib/module/hooks/useCactusLM.js +23 -15
  37. package/lib/module/hooks/useCactusLM.js.map +1 -1
  38. package/lib/module/hooks/useCactusSTT.js +85 -28
  39. package/lib/module/hooks/useCactusSTT.js.map +1 -1
  40. package/lib/module/hooks/useCactusVAD.js +171 -0
  41. package/lib/module/hooks/useCactusVAD.js.map +1 -0
  42. package/lib/module/index.js +2 -3
  43. package/lib/module/index.js.map +1 -1
  44. package/lib/module/modelRegistry.js +52 -0
  45. package/lib/module/modelRegistry.js.map +1 -0
  46. package/lib/module/native/Cactus.js +107 -8
  47. package/lib/module/native/Cactus.js.map +1 -1
  48. package/lib/module/native/CactusIndex.js.map +1 -1
  49. package/lib/module/native/index.js +0 -3
  50. package/lib/module/native/index.js.map +1 -1
  51. package/lib/module/types/CactusLM.js +2 -0
  52. package/lib/module/types/CactusSTT.js +2 -0
  53. package/lib/module/types/CactusVAD.js +4 -0
  54. package/lib/module/types/{CactusModel.js.map → CactusVAD.js.map} +1 -1
  55. package/lib/module/types/common.js +2 -0
  56. package/lib/module/types/{CactusSTTModel.js.map → common.js.map} +1 -1
  57. package/lib/typescript/src/classes/CactusLM.d.ts +8 -6
  58. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  59. package/lib/typescript/src/classes/CactusSTT.d.ts +11 -6
  60. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  61. package/lib/typescript/src/classes/CactusVAD.d.ts +20 -0
  62. package/lib/typescript/src/classes/CactusVAD.d.ts.map +1 -0
  63. package/lib/typescript/src/hooks/useCactusLM.d.ts +3 -3
  64. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  65. package/lib/typescript/src/hooks/useCactusSTT.d.ts +11 -5
  66. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  67. package/lib/typescript/src/hooks/useCactusVAD.d.ts +15 -0
  68. package/lib/typescript/src/hooks/useCactusVAD.d.ts.map +1 -0
  69. package/lib/typescript/src/index.d.ts +7 -6
  70. package/lib/typescript/src/index.d.ts.map +1 -1
  71. package/lib/typescript/src/modelRegistry.d.ts +5 -0
  72. package/lib/typescript/src/modelRegistry.d.ts.map +1 -0
  73. package/lib/typescript/src/native/Cactus.d.ts +12 -6
  74. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  75. package/lib/typescript/src/native/CactusIndex.d.ts +2 -2
  76. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -1
  77. package/lib/typescript/src/native/index.d.ts +0 -3
  78. package/lib/typescript/src/native/index.d.ts.map +1 -1
  79. package/lib/typescript/src/specs/Cactus.nitro.d.ts +6 -1
  80. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  81. package/lib/typescript/src/types/CactusIndex.d.ts +2 -2
  82. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -1
  83. package/lib/typescript/src/types/CactusLM.d.ts +19 -9
  84. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  85. package/lib/typescript/src/types/CactusSTT.d.ts +45 -4
  86. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  87. package/lib/typescript/src/types/CactusVAD.d.ts +34 -0
  88. package/lib/typescript/src/types/CactusVAD.d.ts.map +1 -0
  89. package/lib/typescript/src/types/common.d.ts +23 -0
  90. package/lib/typescript/src/types/common.d.ts.map +1 -0
  91. package/nitro.json +0 -11
  92. package/nitrogen/generated/android/cactus+autolinking.cmake +0 -5
  93. package/nitrogen/generated/android/cactusOnLoad.cpp +0 -30
  94. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +0 -50
  95. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +9 -147
  96. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +0 -13
  97. package/nitrogen/generated/ios/CactusAutolinking.mm +0 -26
  98. package/nitrogen/generated/ios/CactusAutolinking.swift +0 -30
  99. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +5 -0
  100. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +6 -1
  101. package/package.json +3 -3
  102. package/src/classes/CactusLM.ts +59 -74
  103. package/src/classes/CactusSTT.ts +92 -49
  104. package/src/classes/CactusVAD.ts +129 -0
  105. package/src/hooks/useCactusLM.ts +26 -9
  106. package/src/hooks/useCactusSTT.ts +105 -44
  107. package/src/hooks/useCactusVAD.ts +215 -0
  108. package/src/index.tsx +20 -10
  109. package/src/modelRegistry.ts +65 -0
  110. package/src/native/Cactus.ts +130 -14
  111. package/src/native/CactusIndex.ts +2 -2
  112. package/src/native/index.ts +0 -3
  113. package/src/specs/Cactus.nitro.ts +11 -2
  114. package/src/types/CactusIndex.ts +2 -2
  115. package/src/types/CactusLM.ts +20 -9
  116. package/src/types/CactusSTT.ts +50 -4
  117. package/src/types/CactusVAD.ts +39 -0
  118. package/src/types/common.ts +23 -0
  119. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusCrypto.kt +0 -46
  120. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusDeviceInfo.kt +0 -27
  121. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.a +0 -0
  122. package/cpp/HybridCactusUtil.cpp +0 -47
  123. package/cpp/HybridCactusUtil.hpp +0 -27
  124. package/cpp/cactus_util.h +0 -25
  125. package/ios/HybridCactusCrypto.swift +0 -37
  126. package/ios/HybridCactusDeviceInfo.swift +0 -32
  127. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_telemetry.h +0 -656
  128. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_telemetry.h +0 -656
  129. package/ios/cactus_util.xcframework/Info.plist +0 -39
  130. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/cactus_util.h +0 -25
  131. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/database.h +0 -27
  132. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/ios_utils.h +0 -10
  133. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/logging.h +0 -25
  134. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Info.plist +0 -0
  135. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/cactus_util +0 -0
  136. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/cactus_util.h +0 -25
  137. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/database.h +0 -27
  138. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/ios_utils.h +0 -10
  139. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/logging.h +0 -25
  140. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Info.plist +0 -0
  141. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/_CodeSignature/CodeResources +0 -135
  142. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/cactus_util +0 -0
  143. package/lib/module/api/Database.js +0 -137
  144. package/lib/module/api/Database.js.map +0 -1
  145. package/lib/module/api/RemoteLM.js +0 -201
  146. package/lib/module/api/RemoteLM.js.map +0 -1
  147. package/lib/module/config/CactusConfig.js +0 -12
  148. package/lib/module/config/CactusConfig.js.map +0 -1
  149. package/lib/module/native/CactusCrypto.js +0 -10
  150. package/lib/module/native/CactusCrypto.js.map +0 -1
  151. package/lib/module/native/CactusDeviceInfo.js +0 -13
  152. package/lib/module/native/CactusDeviceInfo.js.map +0 -1
  153. package/lib/module/native/CactusUtil.js +0 -36
  154. package/lib/module/native/CactusUtil.js.map +0 -1
  155. package/lib/module/specs/CactusCrypto.nitro.js +0 -4
  156. package/lib/module/specs/CactusCrypto.nitro.js.map +0 -1
  157. package/lib/module/specs/CactusDeviceInfo.nitro.js +0 -4
  158. package/lib/module/specs/CactusDeviceInfo.nitro.js.map +0 -1
  159. package/lib/module/specs/CactusUtil.nitro.js +0 -4
  160. package/lib/module/specs/CactusUtil.nitro.js.map +0 -1
  161. package/lib/module/telemetry/Telemetry.js +0 -154
  162. package/lib/module/telemetry/Telemetry.js.map +0 -1
  163. package/lib/module/types/CactusModel.js +0 -2
  164. package/lib/module/types/CactusSTTModel.js +0 -2
  165. package/lib/typescript/src/api/Database.d.ts +0 -18
  166. package/lib/typescript/src/api/Database.d.ts.map +0 -1
  167. package/lib/typescript/src/api/RemoteLM.d.ts +0 -14
  168. package/lib/typescript/src/api/RemoteLM.d.ts.map +0 -1
  169. package/lib/typescript/src/config/CactusConfig.d.ts +0 -7
  170. package/lib/typescript/src/config/CactusConfig.d.ts.map +0 -1
  171. package/lib/typescript/src/native/CactusCrypto.d.ts +0 -5
  172. package/lib/typescript/src/native/CactusCrypto.d.ts.map +0 -1
  173. package/lib/typescript/src/native/CactusDeviceInfo.d.ts +0 -7
  174. package/lib/typescript/src/native/CactusDeviceInfo.d.ts.map +0 -1
  175. package/lib/typescript/src/native/CactusUtil.d.ts +0 -6
  176. package/lib/typescript/src/native/CactusUtil.d.ts.map +0 -1
  177. package/lib/typescript/src/specs/CactusCrypto.nitro.d.ts +0 -8
  178. package/lib/typescript/src/specs/CactusCrypto.nitro.d.ts.map +0 -1
  179. package/lib/typescript/src/specs/CactusDeviceInfo.nitro.d.ts +0 -16
  180. package/lib/typescript/src/specs/CactusDeviceInfo.nitro.d.ts.map +0 -1
  181. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts +0 -10
  182. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts.map +0 -1
  183. package/lib/typescript/src/telemetry/Telemetry.d.ts +0 -34
  184. package/lib/typescript/src/telemetry/Telemetry.d.ts.map +0 -1
  185. package/lib/typescript/src/types/CactusModel.d.ts +0 -13
  186. package/lib/typescript/src/types/CactusModel.d.ts.map +0 -1
  187. package/lib/typescript/src/types/CactusSTTModel.d.ts +0 -8
  188. package/lib/typescript/src/types/CactusSTTModel.d.ts.map +0 -1
  189. package/nitrogen/generated/android/c++/JDeviceInfo.hpp +0 -74
  190. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +0 -65
  191. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +0 -65
  192. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +0 -85
  193. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +0 -66
  194. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +0 -50
  195. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +0 -58
  196. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +0 -62
  197. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +0 -11
  198. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +0 -77
  199. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +0 -11
  200. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +0 -88
  201. package/nitrogen/generated/ios/swift/DeviceInfo.swift +0 -98
  202. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +0 -47
  203. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -54
  204. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +0 -57
  205. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +0 -139
  206. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +0 -58
  207. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +0 -164
  208. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +0 -92
  209. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +0 -21
  210. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +0 -63
  211. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +0 -22
  212. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +0 -67
  213. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +0 -23
  214. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +0 -66
  215. package/src/api/Database.ts +0 -188
  216. package/src/api/RemoteLM.ts +0 -273
  217. package/src/config/CactusConfig.ts +0 -11
  218. package/src/native/CactusCrypto.ts +0 -11
  219. package/src/native/CactusDeviceInfo.ts +0 -18
  220. package/src/native/CactusUtil.ts +0 -43
  221. package/src/specs/CactusCrypto.nitro.ts +0 -6
  222. package/src/specs/CactusDeviceInfo.nitro.ts +0 -15
  223. package/src/specs/CactusUtil.nitro.ts +0 -8
  224. package/src/telemetry/Telemetry.ts +0 -236
  225. package/src/types/CactusModel.ts +0 -15
  226. package/src/types/CactusSTTModel.ts +0 -10
@@ -0,0 +1,215 @@
1
+ import { useCallback, useEffect, useState, useRef } from 'react';
2
+ import { CactusVAD } from '../classes/CactusVAD';
3
+ import { CactusFileSystem } from '../native';
4
+ import { getErrorMessage } from '../utils/error';
5
+ import type {
6
+ CactusVADParams,
7
+ CactusVADDownloadParams,
8
+ CactusVADVadParams,
9
+ CactusVADResult,
10
+ } from '../types/CactusVAD';
11
+ import type { CactusModel } from '../types/common';
12
+
13
+ export const useCactusVAD = ({
14
+ model = 'silero-vad',
15
+ options: modelOptions = {
16
+ quantization: undefined,
17
+ pro: false,
18
+ },
19
+ }: CactusVADParams = {}) => {
20
+ const [cactusVAD, setCactusVAD] = useState(
21
+ () => new CactusVAD({ model, options: modelOptions })
22
+ );
23
+
24
+ const [isInitializing, setIsInitializing] = useState(false);
25
+ const [isDownloaded, setIsDownloaded] = useState(false);
26
+ const [isDownloading, setIsDownloading] = useState(false);
27
+ const [downloadProgress, setDownloadProgress] = useState(0);
28
+ const [error, setError] = useState<string | null>(null);
29
+
30
+ const currentModelRef = useRef(model);
31
+ const currentDownloadIdRef = useRef(0);
32
+
33
+ useEffect(() => {
34
+ currentModelRef.current = model;
35
+ }, [model]);
36
+
37
+ useEffect(() => {
38
+ const newInstance = new CactusVAD({
39
+ model,
40
+ options: {
41
+ quantization: modelOptions.quantization,
42
+ pro: modelOptions.pro,
43
+ },
44
+ });
45
+ setCactusVAD(newInstance);
46
+
47
+ setIsInitializing(false);
48
+ setIsDownloaded(false);
49
+ setIsDownloading(false);
50
+ setDownloadProgress(0);
51
+ setError(null);
52
+
53
+ let mounted = true;
54
+ CactusFileSystem.modelExists(newInstance.getModelName())
55
+ .then((exists) => {
56
+ if (!mounted) {
57
+ return;
58
+ }
59
+ setIsDownloaded(exists);
60
+ })
61
+ .catch((e) => {
62
+ if (!mounted) {
63
+ return;
64
+ }
65
+ setIsDownloaded(false);
66
+ setError(getErrorMessage(e));
67
+ });
68
+
69
+ return () => {
70
+ mounted = false;
71
+ };
72
+ }, [model, modelOptions.quantization, modelOptions.pro]);
73
+
74
+ useEffect(() => {
75
+ return () => {
76
+ cactusVAD.destroy().catch(() => {});
77
+ };
78
+ }, [cactusVAD]);
79
+
80
+ const download = useCallback(
81
+ async ({ onProgress }: CactusVADDownloadParams = {}) => {
82
+ if (isDownloading) {
83
+ const message = 'CactusVAD is already downloading';
84
+ setError(message);
85
+ throw new Error(message);
86
+ }
87
+
88
+ setError(null);
89
+
90
+ if (isDownloaded) {
91
+ return;
92
+ }
93
+
94
+ const thisModel = currentModelRef.current;
95
+ const thisDownloadId = ++currentDownloadIdRef.current;
96
+
97
+ setDownloadProgress(0);
98
+ setIsDownloading(true);
99
+ try {
100
+ await cactusVAD.download({
101
+ onProgress: (progress) => {
102
+ if (
103
+ currentModelRef.current !== thisModel ||
104
+ currentDownloadIdRef.current !== thisDownloadId
105
+ ) {
106
+ return;
107
+ }
108
+
109
+ setDownloadProgress(progress);
110
+ onProgress?.(progress);
111
+ },
112
+ });
113
+
114
+ if (
115
+ currentModelRef.current !== thisModel ||
116
+ currentDownloadIdRef.current !== thisDownloadId
117
+ ) {
118
+ return;
119
+ }
120
+
121
+ setIsDownloaded(true);
122
+ } catch (e) {
123
+ if (
124
+ currentModelRef.current !== thisModel ||
125
+ currentDownloadIdRef.current !== thisDownloadId
126
+ ) {
127
+ return;
128
+ }
129
+
130
+ setError(getErrorMessage(e));
131
+ throw e;
132
+ } finally {
133
+ if (
134
+ currentModelRef.current !== thisModel ||
135
+ currentDownloadIdRef.current !== thisDownloadId
136
+ ) {
137
+ return;
138
+ }
139
+
140
+ setIsDownloading(false);
141
+ setDownloadProgress(0);
142
+ }
143
+ },
144
+ [cactusVAD, isDownloading, isDownloaded]
145
+ );
146
+
147
+ const init = useCallback(async () => {
148
+ if (isInitializing) {
149
+ const message = 'CactusVAD is already initializing';
150
+ setError(message);
151
+ throw new Error(message);
152
+ }
153
+
154
+ setError(null);
155
+ setIsInitializing(true);
156
+ try {
157
+ await cactusVAD.init();
158
+ } catch (e) {
159
+ setError(getErrorMessage(e));
160
+ throw e;
161
+ } finally {
162
+ setIsInitializing(false);
163
+ }
164
+ }, [cactusVAD, isInitializing]);
165
+
166
+ const vad = useCallback(
167
+ async ({
168
+ audio,
169
+ options,
170
+ }: CactusVADVadParams): Promise<CactusVADResult> => {
171
+ setError(null);
172
+ try {
173
+ return await cactusVAD.vad({ audio, options });
174
+ } catch (e) {
175
+ setError(getErrorMessage(e));
176
+ throw e;
177
+ }
178
+ },
179
+ [cactusVAD]
180
+ );
181
+
182
+ const destroy = useCallback(async () => {
183
+ setError(null);
184
+ try {
185
+ await cactusVAD.destroy();
186
+ } catch (e) {
187
+ setError(getErrorMessage(e));
188
+ throw e;
189
+ }
190
+ }, [cactusVAD]);
191
+
192
+ const getModels = useCallback(async (): Promise<CactusModel[]> => {
193
+ setError(null);
194
+ try {
195
+ return await cactusVAD.getModels();
196
+ } catch (e) {
197
+ setError(getErrorMessage(e));
198
+ throw e;
199
+ }
200
+ }, [cactusVAD]);
201
+
202
+ return {
203
+ isInitializing,
204
+ isDownloaded,
205
+ isDownloading,
206
+ downloadProgress,
207
+ error,
208
+
209
+ download,
210
+ init,
211
+ vad,
212
+ destroy,
213
+ getModels,
214
+ };
215
+ };
package/src/index.tsx CHANGED
@@ -1,22 +1,23 @@
1
1
  // Classes
2
2
  export { CactusLM } from './classes/CactusLM';
3
3
  export { CactusSTT } from './classes/CactusSTT';
4
+ export { CactusVAD } from './classes/CactusVAD';
4
5
  export { CactusIndex } from './classes/CactusIndex';
5
6
 
6
7
  // Hooks
7
8
  export { useCactusLM } from './hooks/useCactusLM';
8
9
  export { useCactusSTT } from './hooks/useCactusSTT';
10
+ export { useCactusVAD } from './hooks/useCactusVAD';
9
11
  export { useCactusIndex } from './hooks/useCactusIndex';
10
12
 
11
13
  // Types
12
- export type { CactusModel } from './types/CactusModel';
13
- export type { CactusSTTModel } from './types/CactusSTTModel';
14
+ export type { CactusModel, CactusModelOptions } from './types/common';
14
15
  export type {
15
16
  CactusLMParams,
16
17
  CactusLMDownloadParams,
17
- Message,
18
- CompleteOptions,
19
- Tool,
18
+ CactusLMMessage,
19
+ CactusLMCompleteOptions,
20
+ CactusLMTool,
20
21
  CactusLMCompleteParams,
21
22
  CactusLMCompleteResult,
22
23
  CactusLMTokenizeParams,
@@ -31,22 +32,31 @@ export type {
31
32
  export type {
32
33
  CactusSTTParams,
33
34
  CactusSTTDownloadParams,
34
- TranscribeOptions,
35
+ CactusSTTTranscribeOptions,
35
36
  CactusSTTTranscribeParams,
36
37
  CactusSTTTranscribeResult,
37
38
  CactusSTTAudioEmbedParams,
38
39
  CactusSTTAudioEmbedResult,
40
+ CactusSTTStreamTranscribeStartOptions,
41
+ CactusSTTStreamTranscribeProcessParams,
42
+ CactusSTTStreamTranscribeProcessResult,
43
+ CactusSTTStreamTranscribeStopResult,
39
44
  } from './types/CactusSTT';
45
+ export type {
46
+ CactusVADParams,
47
+ CactusVADDownloadParams,
48
+ CactusVADVadParams,
49
+ CactusVADOptions,
50
+ CactusVADSegment,
51
+ CactusVADResult,
52
+ } from './types/CactusVAD';
40
53
  export type {
41
54
  CactusIndexParams,
42
55
  CactusIndexAddParams,
43
56
  CactusIndexGetParams,
44
57
  CactusIndexGetResult,
45
- IndexQueryOptions,
58
+ CactusIndexQueryOptions,
46
59
  CactusIndexQueryParams,
47
60
  CactusIndexQueryResult,
48
61
  CactusIndexDeleteParams,
49
62
  } from './types/CactusIndex';
50
-
51
- // Config
52
- export { CactusConfig } from './config/CactusConfig';
@@ -0,0 +1,65 @@
1
+ import type { CactusModel } from './types/common';
2
+
3
+ const VERSION = 'v1.7';
4
+
5
+ let registryPromise: Promise<{ [key: string]: CactusModel }> | null = null;
6
+
7
+ export function getRegistry(): Promise<{ [key: string]: CactusModel }> {
8
+ return (registryPromise ??= fetchRegistry());
9
+ }
10
+
11
+ async function fetchRegistry(): Promise<{ [key: string]: CactusModel }> {
12
+ const response = await fetch(
13
+ 'https://huggingface.co/api/models?author=Cactus-Compute&full=true'
14
+ ).catch((e) => {
15
+ registryPromise = null;
16
+ throw e;
17
+ });
18
+ if (!response.ok) {
19
+ registryPromise = null;
20
+ throw new Error(`Failed to fetch model registry: ${response.status}`);
21
+ }
22
+
23
+ const models: any[] = await response.json();
24
+ const registry: { [key: string]: CactusModel } = {};
25
+
26
+ for (const { id, siblings = [] } of models) {
27
+ const weights: string[] = siblings
28
+ .map((s: any) => s.rfilename)
29
+ .filter((f: string) => f.startsWith('weights/') && f.endsWith('.zip'));
30
+
31
+ if (
32
+ !weights.some((f) => f.endsWith('-int4.zip')) ||
33
+ !weights.some((f) => f.endsWith('-int8.zip'))
34
+ )
35
+ continue;
36
+
37
+ const key = weights
38
+ .find((f) => f.endsWith('-int4.zip'))!
39
+ .replace('weights/', '')
40
+ .replace('-int4.zip', '');
41
+
42
+ const base = `https://huggingface.co/${id}/resolve/${VERSION}/weights/${key}`;
43
+
44
+ registry[key] = {
45
+ quantization: {
46
+ int4: {
47
+ sizeMb: 0,
48
+ url: `${base}-int4.zip`,
49
+ ...(weights.some((f) => f.endsWith('-int4-apple.zip'))
50
+ ? { pro: { apple: `${base}-int4-apple.zip` } }
51
+ : {}),
52
+ },
53
+ int8: {
54
+ sizeMb: 0,
55
+ url: `${base}-int8.zip`,
56
+ ...(weights.some((f) => f.endsWith('-int8-apple.zip'))
57
+ ? { pro: { apple: `${base}-int8-apple.zip` } }
58
+ : {}),
59
+ },
60
+ },
61
+ };
62
+ }
63
+
64
+ return registry;
65
+ }
@@ -3,14 +3,18 @@ import type { Cactus as CactusSpec } from '../specs/Cactus.nitro';
3
3
  import { CactusImage } from './CactusImage';
4
4
  import type {
5
5
  CactusLMCompleteResult,
6
- Message,
7
- CompleteOptions,
8
- Tool,
6
+ CactusLMMessage,
7
+ CactusLMCompleteOptions,
8
+ CactusLMTool,
9
9
  } from '../types/CactusLM';
10
10
  import type {
11
11
  CactusSTTTranscribeResult,
12
- TranscribeOptions,
12
+ CactusSTTTranscribeOptions,
13
+ CactusSTTStreamTranscribeStartOptions,
14
+ CactusSTTStreamTranscribeProcessResult,
15
+ CactusSTTStreamTranscribeStopResult,
13
16
  } from '../types/CactusSTT';
17
+ import type { CactusVADOptions, CactusVADResult } from '../types/CactusVAD';
14
18
 
15
19
  export class Cactus {
16
20
  private readonly hybridCactus =
@@ -18,20 +22,20 @@ export class Cactus {
18
22
 
19
23
  public init(
20
24
  modelPath: string,
21
- contextSize: number,
22
- corpusDir?: string
25
+ corpusDir?: string,
26
+ cacheIndex?: boolean
23
27
  ): Promise<void> {
24
- return this.hybridCactus.init(modelPath, contextSize, corpusDir);
28
+ return this.hybridCactus.init(modelPath, corpusDir, cacheIndex ?? false);
25
29
  }
26
30
 
27
31
  public async complete(
28
- messages: Message[],
32
+ messages: CactusLMMessage[],
29
33
  responseBufferSize: number,
30
- options?: CompleteOptions,
31
- tools?: { type: 'function'; function: Tool }[],
34
+ options?: CactusLMCompleteOptions,
35
+ tools?: { type: 'function'; function: CactusLMTool }[],
32
36
  callback?: (token: string, tokenId: number) => void
33
37
  ): Promise<CactusLMCompleteResult> {
34
- const messagesInternal: Message[] = [];
38
+ const messagesInternal: CactusLMMessage[] = [];
35
39
  for (const message of messages) {
36
40
  if (!message.images) {
37
41
  messagesInternal.push(message);
@@ -61,6 +65,11 @@ export class Cactus {
61
65
  max_tokens: options.maxTokens,
62
66
  stop_sequences: options.stopSequences,
63
67
  force_tools: options.forceTools,
68
+ telemetry_enabled: options.telemetryEnabled,
69
+ confidence_threshold: options.confidenceThreshold,
70
+ tool_rag_top_k: options.toolRagTopK,
71
+ include_stop_sequences: options.includeStopSequences,
72
+ use_vad: options.useVad,
64
73
  })
65
74
  : undefined;
66
75
  const toolsJson = JSON.stringify(tools);
@@ -80,12 +89,16 @@ export class Cactus {
80
89
  success: parsed.success,
81
90
  response: parsed.response,
82
91
  functionCalls: parsed.function_calls,
92
+ cloudHandoff: parsed.cloud_handoff,
93
+ confidence: parsed.confidence,
83
94
  timeToFirstTokenMs: parsed.time_to_first_token_ms,
84
95
  totalTimeMs: parsed.total_time_ms,
85
- tokensPerSecond: parsed.tokens_per_second,
86
96
  prefillTokens: parsed.prefill_tokens,
97
+ prefillTps: parsed.prefill_tps,
87
98
  decodeTokens: parsed.decode_tokens,
99
+ decodeTps: parsed.decode_tps,
88
100
  totalTokens: parsed.total_tokens,
101
+ ramUsageMb: parsed.ram_usage_mb,
89
102
  };
90
103
  } catch {
91
104
  throw new Error('Unable to parse completion response');
@@ -120,7 +133,7 @@ export class Cactus {
120
133
  audio: string | number[],
121
134
  prompt: string,
122
135
  responseBufferSize: number,
123
- options?: TranscribeOptions,
136
+ options?: CactusSTTTranscribeOptions,
124
137
  callback?: (token: string, tokenId: number) => void
125
138
  ): Promise<CactusSTTTranscribeResult> {
126
139
  if (typeof audio === 'string') {
@@ -134,6 +147,11 @@ export class Cactus {
134
147
  top_k: options.topK,
135
148
  max_tokens: options.maxTokens,
136
149
  stop_sequences: options.stopSequences,
150
+ use_vad: options.useVad,
151
+ telemetry_enabled: options.telemetryEnabled,
152
+ confidence_threshold: options.confidenceThreshold,
153
+ cloud_handoff_threshold: options.cloudHandoffThreshold,
154
+ include_stop_sequences: options.includeStopSequences,
137
155
  })
138
156
  : undefined;
139
157
 
@@ -151,18 +169,112 @@ export class Cactus {
151
169
  return {
152
170
  success: parsed.success,
153
171
  response: parsed.response,
172
+ cloudHandoff: parsed.cloud_handoff,
173
+ confidence: parsed.confidence,
154
174
  timeToFirstTokenMs: parsed.time_to_first_token_ms,
155
175
  totalTimeMs: parsed.total_time_ms,
156
- tokensPerSecond: parsed.tokens_per_second,
157
176
  prefillTokens: parsed.prefill_tokens,
177
+ prefillTps: parsed.prefill_tps,
158
178
  decodeTokens: parsed.decode_tokens,
179
+ decodeTps: parsed.decode_tps,
159
180
  totalTokens: parsed.total_tokens,
181
+ ramUsageMb: parsed.ram_usage_mb,
160
182
  };
161
183
  } catch {
162
184
  throw new Error('Unable to parse transcription response');
163
185
  }
164
186
  }
165
187
 
188
+ public streamTranscribeStart(
189
+ options?: CactusSTTStreamTranscribeStartOptions
190
+ ): Promise<void> {
191
+ const optionsJson = options
192
+ ? JSON.stringify({
193
+ confirmation_threshold: options.confirmationThreshold,
194
+ min_chunk_size: options.minChunkSize,
195
+ telemetry_enabled: options.telemetryEnabled,
196
+ })
197
+ : undefined;
198
+ return this.hybridCactus.streamTranscribeStart(optionsJson);
199
+ }
200
+
201
+ public async streamTranscribeProcess(
202
+ audio: number[]
203
+ ): Promise<CactusSTTStreamTranscribeProcessResult> {
204
+ const response = await this.hybridCactus.streamTranscribeProcess(audio);
205
+ try {
206
+ const parsed = JSON.parse(response);
207
+ return {
208
+ success: parsed.success,
209
+ confirmed: parsed.confirmed,
210
+ pending: parsed.pending,
211
+ bufferDurationMs: parsed.buffer_duration_ms,
212
+ confidence: parsed.confidence,
213
+ cloudHandoff: parsed.cloud_handoff,
214
+ cloudResult: parsed.cloud_result,
215
+ cloudJobId: parsed.cloud_job_id,
216
+ cloudResultJobId: parsed.cloud_result_job_id,
217
+ timeToFirstTokenMs: parsed.time_to_first_token_ms,
218
+ totalTimeMs: parsed.total_time_ms,
219
+ prefillTokens: parsed.prefill_tokens,
220
+ prefillTps: parsed.prefill_tps,
221
+ decodeTokens: parsed.decode_tokens,
222
+ decodeTps: parsed.decode_tps,
223
+ totalTokens: parsed.total_tokens,
224
+ ramUsageMb: parsed.ram_usage_mb,
225
+ };
226
+ } catch {
227
+ throw new Error('Unable to parse stream transcribe process response');
228
+ }
229
+ }
230
+
231
+ public async streamTranscribeStop(): Promise<CactusSTTStreamTranscribeStopResult> {
232
+ const response = await this.hybridCactus.streamTranscribeStop();
233
+ try {
234
+ const parsed = JSON.parse(response);
235
+ return { success: parsed.success, confirmed: parsed.confirmed };
236
+ } catch {
237
+ throw new Error('Unable to parse stream transcribe stop response');
238
+ }
239
+ }
240
+
241
+ public async vad(
242
+ audio: string | number[],
243
+ options?: CactusVADOptions
244
+ ): Promise<CactusVADResult> {
245
+ if (typeof audio === 'string') {
246
+ audio = audio.replace('file://', '');
247
+ }
248
+ const optionsJson = options
249
+ ? JSON.stringify({
250
+ threshold: options.threshold,
251
+ neg_threshold: options.negThreshold,
252
+ min_speech_duration_ms: options.minSpeechDurationMs,
253
+ max_speech_duration_s: options.maxSpeechDurationS,
254
+ min_silence_duration_ms: options.minSilenceDurationMs,
255
+ speech_pad_ms: options.speechPadMs,
256
+ window_size_samples: options.windowSizeSamples,
257
+ sampling_rate: options.samplingRate,
258
+ min_silence_at_max_speech: options.minSilenceAtMaxSpeech,
259
+ use_max_poss_sil_at_max_speech: options.useMaxPossSilAtMaxSpeech,
260
+ })
261
+ : undefined;
262
+ const response = await this.hybridCactus.vad(audio, 65536, optionsJson);
263
+ try {
264
+ const parsed = JSON.parse(response);
265
+ return {
266
+ segments: parsed.segments.map((s: { start: number; end: number }) => ({
267
+ start: s.start,
268
+ end: s.end,
269
+ })),
270
+ totalTime: parsed.total_time_ms,
271
+ ramUsage: parsed.ram_usage_mb,
272
+ };
273
+ } catch {
274
+ throw new Error('Unable to parse VAD response');
275
+ }
276
+ }
277
+
166
278
  public embed(
167
279
  text: string,
168
280
  embeddingBufferSize: number,
@@ -205,4 +317,8 @@ export class Cactus {
205
317
  public destroy(): Promise<void> {
206
318
  return this.hybridCactus.destroy();
207
319
  }
320
+
321
+ public setTelemetryEnvironment(cacheDir: string): Promise<void> {
322
+ return this.hybridCactus.setTelemetryEnvironment(cacheDir);
323
+ }
208
324
  }
@@ -3,7 +3,7 @@ import type { CactusIndex as CactusIndexSpec } from '../specs/CactusIndex.nitro'
3
3
  import type {
4
4
  CactusIndexGetResult,
5
5
  CactusIndexQueryResult,
6
- IndexQueryOptions,
6
+ CactusIndexQueryOptions,
7
7
  } from '../types/CactusIndex';
8
8
 
9
9
  export class CactusIndex {
@@ -33,7 +33,7 @@ export class CactusIndex {
33
33
 
34
34
  public query(
35
35
  embeddings: number[][],
36
- options?: IndexQueryOptions
36
+ options?: CactusIndexQueryOptions
37
37
  ): Promise<CactusIndexQueryResult> {
38
38
  const optionsJson = options
39
39
  ? JSON.stringify({
@@ -1,7 +1,4 @@
1
1
  export { Cactus } from './Cactus';
2
2
  export { CactusIndex } from './CactusIndex';
3
- export { CactusCrypto } from './CactusCrypto';
4
- export { CactusDeviceInfo } from './CactusDeviceInfo';
5
3
  export { CactusFileSystem } from './CactusFileSystem';
6
4
  export { CactusImage } from './CactusImage';
7
- export { CactusUtil } from './CactusUtil';
@@ -3,8 +3,8 @@ import type { HybridObject } from 'react-native-nitro-modules';
3
3
  export interface Cactus extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
4
4
  init(
5
5
  modelPath: string,
6
- contextSize: number,
7
- corpusDir?: string
6
+ corpusDir?: string,
7
+ cacheIndex?: boolean
8
8
  ): Promise<void>;
9
9
  complete(
10
10
  messagesJson: string,
@@ -27,6 +27,14 @@ export interface Cactus extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
27
27
  optionsJson?: string,
28
28
  callback?: (token: string, tokenId: number) => void
29
29
  ): Promise<string>;
30
+ streamTranscribeStart(optionsJson?: string): Promise<void>;
31
+ streamTranscribeProcess(audio: number[]): Promise<string>;
32
+ streamTranscribeStop(): Promise<string>;
33
+ vad(
34
+ audio: string | number[],
35
+ responseBufferSize: number,
36
+ optionsJson?: string
37
+ ): Promise<string>;
30
38
  embed(
31
39
  text: string,
32
40
  embeddingBufferSize: number,
@@ -37,4 +45,5 @@ export interface Cactus extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
37
45
  reset(): Promise<void>;
38
46
  stop(): Promise<void>;
39
47
  destroy(): Promise<void>;
48
+ setTelemetryEnvironment(cacheDir: string): Promise<void>;
40
49
  }
@@ -20,14 +20,14 @@ export interface CactusIndexGetResult {
20
20
  embeddings: number[][];
21
21
  }
22
22
 
23
- export interface IndexQueryOptions {
23
+ export interface CactusIndexQueryOptions {
24
24
  topK?: number;
25
25
  scoreThreshold?: number;
26
26
  }
27
27
 
28
28
  export interface CactusIndexQueryParams {
29
29
  embeddings: number[][];
30
- options?: IndexQueryOptions;
30
+ options?: CactusIndexQueryOptions;
31
31
  }
32
32
 
33
33
  export interface CactusIndexQueryResult {