cactus-react-native 1.5.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 (216) hide show
  1. package/Cactus.podspec +1 -1
  2. package/README.md +347 -241
  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 +149 -117
  10. package/cpp/HybridCactus.hpp +14 -10
  11. package/cpp/cactus_ffi.h +54 -43
  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 +54 -43
  14. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_utils.h +318 -123
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +118 -15
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +77 -32
  17. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +68 -6
  18. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel_utils.h +21 -155
  19. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  20. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus.h +0 -1
  21. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +54 -43
  22. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_utils.h +318 -123
  23. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +118 -15
  24. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +77 -32
  25. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +68 -6
  26. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel_utils.h +21 -155
  27. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  28. package/lib/module/classes/CactusLM.js +16 -49
  29. package/lib/module/classes/CactusLM.js.map +1 -1
  30. package/lib/module/classes/CactusSTT.js +30 -79
  31. package/lib/module/classes/CactusSTT.js.map +1 -1
  32. package/lib/module/classes/CactusVAD.js +95 -0
  33. package/lib/module/classes/CactusVAD.js.map +1 -0
  34. package/lib/module/hooks/useCactusLM.js +10 -11
  35. package/lib/module/hooks/useCactusLM.js.map +1 -1
  36. package/lib/module/hooks/useCactusSTT.js +23 -62
  37. package/lib/module/hooks/useCactusSTT.js.map +1 -1
  38. package/lib/module/hooks/useCactusVAD.js +171 -0
  39. package/lib/module/hooks/useCactusVAD.js.map +1 -0
  40. package/lib/module/index.js +2 -3
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/modelRegistry.js +52 -0
  43. package/lib/module/modelRegistry.js.map +1 -0
  44. package/lib/module/native/Cactus.js +85 -23
  45. package/lib/module/native/Cactus.js.map +1 -1
  46. package/lib/module/native/CactusIndex.js.map +1 -1
  47. package/lib/module/native/index.js +0 -3
  48. package/lib/module/native/index.js.map +1 -1
  49. package/lib/module/types/CactusVAD.js +4 -0
  50. package/lib/module/{specs/CactusUtil.nitro.js.map → types/CactusVAD.js.map} +1 -1
  51. package/lib/typescript/src/classes/CactusLM.d.ts +5 -7
  52. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  53. package/lib/typescript/src/classes/CactusSTT.d.ts +8 -12
  54. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  55. package/lib/typescript/src/classes/CactusVAD.d.ts +20 -0
  56. package/lib/typescript/src/classes/CactusVAD.d.ts.map +1 -0
  57. package/lib/typescript/src/hooks/useCactusLM.d.ts +2 -2
  58. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  59. package/lib/typescript/src/hooks/useCactusSTT.d.ts +6 -8
  60. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  61. package/lib/typescript/src/hooks/useCactusVAD.d.ts +15 -0
  62. package/lib/typescript/src/hooks/useCactusVAD.d.ts.map +1 -0
  63. package/lib/typescript/src/index.d.ts +7 -5
  64. package/lib/typescript/src/index.d.ts.map +1 -1
  65. package/lib/typescript/src/modelRegistry.d.ts +5 -0
  66. package/lib/typescript/src/modelRegistry.d.ts.map +1 -0
  67. package/lib/typescript/src/native/Cactus.d.ts +12 -11
  68. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  69. package/lib/typescript/src/native/CactusIndex.d.ts +2 -2
  70. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -1
  71. package/lib/typescript/src/native/index.d.ts +0 -3
  72. package/lib/typescript/src/native/index.d.ts.map +1 -1
  73. package/lib/typescript/src/specs/Cactus.nitro.d.ts +6 -6
  74. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  75. package/lib/typescript/src/types/CactusIndex.d.ts +2 -2
  76. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -1
  77. package/lib/typescript/src/types/CactusLM.d.ts +19 -11
  78. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  79. package/lib/typescript/src/types/CactusSTT.d.ts +33 -12
  80. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  81. package/lib/typescript/src/types/CactusVAD.d.ts +34 -0
  82. package/lib/typescript/src/types/CactusVAD.d.ts.map +1 -0
  83. package/lib/typescript/src/types/common.d.ts +1 -6
  84. package/lib/typescript/src/types/common.d.ts.map +1 -1
  85. package/nitro.json +0 -11
  86. package/nitrogen/generated/android/cactus+autolinking.cmake +0 -5
  87. package/nitrogen/generated/android/cactusOnLoad.cpp +0 -30
  88. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +0 -50
  89. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +9 -147
  90. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +0 -13
  91. package/nitrogen/generated/ios/CactusAutolinking.mm +0 -26
  92. package/nitrogen/generated/ios/CactusAutolinking.swift +0 -30
  93. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +4 -4
  94. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +6 -6
  95. package/package.json +3 -3
  96. package/src/classes/CactusLM.ts +18 -65
  97. package/src/classes/CactusSTT.ts +39 -97
  98. package/src/classes/CactusVAD.ts +129 -0
  99. package/src/hooks/useCactusLM.ts +14 -17
  100. package/src/hooks/useCactusSTT.ts +47 -98
  101. package/src/hooks/useCactusVAD.ts +215 -0
  102. package/src/index.tsx +18 -12
  103. package/src/modelRegistry.ts +65 -0
  104. package/src/native/Cactus.ts +102 -41
  105. package/src/native/CactusIndex.ts +2 -2
  106. package/src/native/index.ts +0 -3
  107. package/src/specs/Cactus.nitro.ts +11 -7
  108. package/src/types/CactusIndex.ts +2 -2
  109. package/src/types/CactusLM.ts +19 -11
  110. package/src/types/CactusSTT.ts +33 -13
  111. package/src/types/CactusVAD.ts +39 -0
  112. package/src/types/common.ts +1 -6
  113. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusCrypto.kt +0 -46
  114. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusDeviceInfo.kt +0 -27
  115. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.a +0 -0
  116. package/cpp/HybridCactusUtil.cpp +0 -47
  117. package/cpp/HybridCactusUtil.hpp +0 -27
  118. package/cpp/cactus_util.h +0 -25
  119. package/ios/HybridCactusCrypto.swift +0 -37
  120. package/ios/HybridCactusDeviceInfo.swift +0 -32
  121. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_telemetry.h +0 -656
  122. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_telemetry.h +0 -656
  123. package/ios/cactus_util.xcframework/Info.plist +0 -39
  124. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/cactus_util.h +0 -25
  125. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/database.h +0 -27
  126. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/ios_utils.h +0 -10
  127. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/logging.h +0 -25
  128. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Info.plist +0 -0
  129. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/cactus_util +0 -0
  130. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/cactus_util.h +0 -25
  131. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/database.h +0 -27
  132. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/ios_utils.h +0 -10
  133. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/logging.h +0 -25
  134. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Info.plist +0 -0
  135. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/_CodeSignature/CodeResources +0 -135
  136. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/cactus_util +0 -0
  137. package/lib/module/api/Database.js +0 -45
  138. package/lib/module/api/Database.js.map +0 -1
  139. package/lib/module/api/RemoteLM.js +0 -201
  140. package/lib/module/api/RemoteLM.js.map +0 -1
  141. package/lib/module/config/CactusConfig.js +0 -12
  142. package/lib/module/config/CactusConfig.js.map +0 -1
  143. package/lib/module/models.js +0 -336
  144. package/lib/module/models.js.map +0 -1
  145. package/lib/module/native/CactusCrypto.js +0 -10
  146. package/lib/module/native/CactusCrypto.js.map +0 -1
  147. package/lib/module/native/CactusDeviceInfo.js +0 -13
  148. package/lib/module/native/CactusDeviceInfo.js.map +0 -1
  149. package/lib/module/native/CactusUtil.js +0 -36
  150. package/lib/module/native/CactusUtil.js.map +0 -1
  151. package/lib/module/specs/CactusCrypto.nitro.js +0 -4
  152. package/lib/module/specs/CactusCrypto.nitro.js.map +0 -1
  153. package/lib/module/specs/CactusDeviceInfo.nitro.js +0 -4
  154. package/lib/module/specs/CactusDeviceInfo.nitro.js.map +0 -1
  155. package/lib/module/specs/CactusUtil.nitro.js +0 -4
  156. package/lib/module/telemetry/Telemetry.js +0 -154
  157. package/lib/module/telemetry/Telemetry.js.map +0 -1
  158. package/lib/typescript/src/api/Database.d.ts +0 -12
  159. package/lib/typescript/src/api/Database.d.ts.map +0 -1
  160. package/lib/typescript/src/api/RemoteLM.d.ts +0 -14
  161. package/lib/typescript/src/api/RemoteLM.d.ts.map +0 -1
  162. package/lib/typescript/src/config/CactusConfig.d.ts +0 -7
  163. package/lib/typescript/src/config/CactusConfig.d.ts.map +0 -1
  164. package/lib/typescript/src/models.d.ts +0 -6
  165. package/lib/typescript/src/models.d.ts.map +0 -1
  166. package/lib/typescript/src/native/CactusCrypto.d.ts +0 -5
  167. package/lib/typescript/src/native/CactusCrypto.d.ts.map +0 -1
  168. package/lib/typescript/src/native/CactusDeviceInfo.d.ts +0 -7
  169. package/lib/typescript/src/native/CactusDeviceInfo.d.ts.map +0 -1
  170. package/lib/typescript/src/native/CactusUtil.d.ts +0 -6
  171. package/lib/typescript/src/native/CactusUtil.d.ts.map +0 -1
  172. package/lib/typescript/src/specs/CactusCrypto.nitro.d.ts +0 -8
  173. package/lib/typescript/src/specs/CactusCrypto.nitro.d.ts.map +0 -1
  174. package/lib/typescript/src/specs/CactusDeviceInfo.nitro.d.ts +0 -16
  175. package/lib/typescript/src/specs/CactusDeviceInfo.nitro.d.ts.map +0 -1
  176. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts +0 -10
  177. package/lib/typescript/src/specs/CactusUtil.nitro.d.ts.map +0 -1
  178. package/lib/typescript/src/telemetry/Telemetry.d.ts +0 -34
  179. package/lib/typescript/src/telemetry/Telemetry.d.ts.map +0 -1
  180. package/nitrogen/generated/android/c++/JDeviceInfo.hpp +0 -74
  181. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +0 -65
  182. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +0 -65
  183. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +0 -85
  184. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +0 -66
  185. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +0 -50
  186. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +0 -58
  187. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +0 -62
  188. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +0 -11
  189. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +0 -77
  190. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +0 -11
  191. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +0 -88
  192. package/nitrogen/generated/ios/swift/DeviceInfo.swift +0 -98
  193. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +0 -47
  194. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -54
  195. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +0 -57
  196. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +0 -139
  197. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +0 -58
  198. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +0 -164
  199. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +0 -92
  200. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +0 -21
  201. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +0 -63
  202. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +0 -22
  203. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +0 -67
  204. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +0 -23
  205. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +0 -66
  206. package/src/api/Database.ts +0 -55
  207. package/src/api/RemoteLM.ts +0 -273
  208. package/src/config/CactusConfig.ts +0 -11
  209. package/src/models.ts +0 -344
  210. package/src/native/CactusCrypto.ts +0 -11
  211. package/src/native/CactusDeviceInfo.ts +0 -18
  212. package/src/native/CactusUtil.ts +0 -43
  213. package/src/specs/CactusCrypto.nitro.ts +0 -6
  214. package/src/specs/CactusDeviceInfo.nitro.ts +0 -15
  215. package/src/specs/CactusUtil.nitro.ts +0 -8
  216. package/src/telemetry/Telemetry.ts +0 -236
@@ -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,21 +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, ModelOptions } from './types/common';
14
+ export type { CactusModel, CactusModelOptions } from './types/common';
13
15
  export type {
14
16
  CactusLMParams,
15
17
  CactusLMDownloadParams,
16
- Message,
17
- CompleteOptions,
18
- Tool,
18
+ CactusLMMessage,
19
+ CactusLMCompleteOptions,
20
+ CactusLMTool,
19
21
  CactusLMCompleteParams,
20
22
  CactusLMCompleteResult,
21
23
  CactusLMTokenizeParams,
@@ -30,27 +32,31 @@ export type {
30
32
  export type {
31
33
  CactusSTTParams,
32
34
  CactusSTTDownloadParams,
33
- TranscribeOptions,
35
+ CactusSTTTranscribeOptions,
34
36
  CactusSTTTranscribeParams,
35
37
  CactusSTTTranscribeResult,
36
38
  CactusSTTAudioEmbedParams,
37
39
  CactusSTTAudioEmbedResult,
38
- CactusSTTStreamTranscribeInsertParams,
39
- StreamTranscribeProcessOptions,
40
+ CactusSTTStreamTranscribeStartOptions,
40
41
  CactusSTTStreamTranscribeProcessParams,
41
42
  CactusSTTStreamTranscribeProcessResult,
42
- CactusSTTStreamTranscribeFinalizeResult,
43
+ CactusSTTStreamTranscribeStopResult,
43
44
  } from './types/CactusSTT';
45
+ export type {
46
+ CactusVADParams,
47
+ CactusVADDownloadParams,
48
+ CactusVADVadParams,
49
+ CactusVADOptions,
50
+ CactusVADSegment,
51
+ CactusVADResult,
52
+ } from './types/CactusVAD';
44
53
  export type {
45
54
  CactusIndexParams,
46
55
  CactusIndexAddParams,
47
56
  CactusIndexGetParams,
48
57
  CactusIndexGetResult,
49
- IndexQueryOptions,
58
+ CactusIndexQueryOptions,
50
59
  CactusIndexQueryParams,
51
60
  CactusIndexQueryResult,
52
61
  CactusIndexDeleteParams,
53
62
  } from './types/CactusIndex';
54
-
55
- // Config
56
- 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,17 +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,
13
14
  CactusSTTStreamTranscribeProcessResult,
14
- StreamTranscribeProcessOptions,
15
- CactusSTTStreamTranscribeFinalizeResult,
15
+ CactusSTTStreamTranscribeStopResult,
16
16
  } from '../types/CactusSTT';
17
+ import type { CactusVADOptions, CactusVADResult } from '../types/CactusVAD';
17
18
 
18
19
  export class Cactus {
19
20
  private readonly hybridCactus =
@@ -21,20 +22,20 @@ export class Cactus {
21
22
 
22
23
  public init(
23
24
  modelPath: string,
24
- contextSize: number,
25
- corpusDir?: string
25
+ corpusDir?: string,
26
+ cacheIndex?: boolean
26
27
  ): Promise<void> {
27
- return this.hybridCactus.init(modelPath, contextSize, corpusDir);
28
+ return this.hybridCactus.init(modelPath, corpusDir, cacheIndex ?? false);
28
29
  }
29
30
 
30
31
  public async complete(
31
- messages: Message[],
32
+ messages: CactusLMMessage[],
32
33
  responseBufferSize: number,
33
- options?: CompleteOptions,
34
- tools?: { type: 'function'; function: Tool }[],
34
+ options?: CactusLMCompleteOptions,
35
+ tools?: { type: 'function'; function: CactusLMTool }[],
35
36
  callback?: (token: string, tokenId: number) => void
36
37
  ): Promise<CactusLMCompleteResult> {
37
- const messagesInternal: Message[] = [];
38
+ const messagesInternal: CactusLMMessage[] = [];
38
39
  for (const message of messages) {
39
40
  if (!message.images) {
40
41
  messagesInternal.push(message);
@@ -64,6 +65,11 @@ export class Cactus {
64
65
  max_tokens: options.maxTokens,
65
66
  stop_sequences: options.stopSequences,
66
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,
67
73
  })
68
74
  : undefined;
69
75
  const toolsJson = JSON.stringify(tools);
@@ -83,12 +89,16 @@ export class Cactus {
83
89
  success: parsed.success,
84
90
  response: parsed.response,
85
91
  functionCalls: parsed.function_calls,
92
+ cloudHandoff: parsed.cloud_handoff,
93
+ confidence: parsed.confidence,
86
94
  timeToFirstTokenMs: parsed.time_to_first_token_ms,
87
95
  totalTimeMs: parsed.total_time_ms,
88
- tokensPerSecond: parsed.tokens_per_second,
89
96
  prefillTokens: parsed.prefill_tokens,
97
+ prefillTps: parsed.prefill_tps,
90
98
  decodeTokens: parsed.decode_tokens,
99
+ decodeTps: parsed.decode_tps,
91
100
  totalTokens: parsed.total_tokens,
101
+ ramUsageMb: parsed.ram_usage_mb,
92
102
  };
93
103
  } catch {
94
104
  throw new Error('Unable to parse completion response');
@@ -123,7 +133,7 @@ export class Cactus {
123
133
  audio: string | number[],
124
134
  prompt: string,
125
135
  responseBufferSize: number,
126
- options?: TranscribeOptions,
136
+ options?: CactusSTTTranscribeOptions,
127
137
  callback?: (token: string, tokenId: number) => void
128
138
  ): Promise<CactusSTTTranscribeResult> {
129
139
  if (typeof audio === 'string') {
@@ -137,6 +147,11 @@ export class Cactus {
137
147
  top_k: options.topK,
138
148
  max_tokens: options.maxTokens,
139
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,
140
155
  })
141
156
  : undefined;
142
157
 
@@ -154,70 +169,112 @@ export class Cactus {
154
169
  return {
155
170
  success: parsed.success,
156
171
  response: parsed.response,
172
+ cloudHandoff: parsed.cloud_handoff,
173
+ confidence: parsed.confidence,
157
174
  timeToFirstTokenMs: parsed.time_to_first_token_ms,
158
175
  totalTimeMs: parsed.total_time_ms,
159
- tokensPerSecond: parsed.tokens_per_second,
160
176
  prefillTokens: parsed.prefill_tokens,
177
+ prefillTps: parsed.prefill_tps,
161
178
  decodeTokens: parsed.decode_tokens,
179
+ decodeTps: parsed.decode_tps,
162
180
  totalTokens: parsed.total_tokens,
181
+ ramUsageMb: parsed.ram_usage_mb,
163
182
  };
164
183
  } catch {
165
184
  throw new Error('Unable to parse transcription response');
166
185
  }
167
186
  }
168
187
 
169
- public streamTranscribeInit(): Promise<void> {
170
- return this.hybridCactus.streamTranscribeInit();
171
- }
172
-
173
- public streamTranscribeInsert(audio: number[]): Promise<void> {
174
- return this.hybridCactus.streamTranscribeInsert(audio);
175
- }
176
-
177
- public async streamTranscribeProcess(
178
- options?: StreamTranscribeProcessOptions
179
- ): Promise<CactusSTTStreamTranscribeProcessResult> {
188
+ public streamTranscribeStart(
189
+ options?: CactusSTTStreamTranscribeStartOptions
190
+ ): Promise<void> {
180
191
  const optionsJson = options
181
192
  ? JSON.stringify({
182
193
  confirmation_threshold: options.confirmationThreshold,
194
+ min_chunk_size: options.minChunkSize,
195
+ telemetry_enabled: options.telemetryEnabled,
183
196
  })
184
197
  : undefined;
198
+ return this.hybridCactus.streamTranscribeStart(optionsJson);
199
+ }
185
200
 
186
- const response =
187
- await this.hybridCactus.streamTranscribeProcess(optionsJson);
188
-
201
+ public async streamTranscribeProcess(
202
+ audio: number[]
203
+ ): Promise<CactusSTTStreamTranscribeProcessResult> {
204
+ const response = await this.hybridCactus.streamTranscribeProcess(audio);
189
205
  try {
190
206
  const parsed = JSON.parse(response);
191
-
192
207
  return {
193
208
  success: parsed.success,
194
209
  confirmed: parsed.confirmed,
195
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,
196
225
  };
197
226
  } catch {
198
227
  throw new Error('Unable to parse stream transcribe process response');
199
228
  }
200
229
  }
201
230
 
202
- public async streamTranscribeFinalize(): Promise<CactusSTTStreamTranscribeFinalizeResult> {
203
- const response = await this.hybridCactus.streamTranscribeFinalize();
204
-
231
+ public async streamTranscribeStop(): Promise<CactusSTTStreamTranscribeStopResult> {
232
+ const response = await this.hybridCactus.streamTranscribeStop();
205
233
  try {
206
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
+ }
207
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);
208
265
  return {
209
- success: parsed.success,
210
- confirmed: parsed.confirmed,
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,
211
272
  };
212
273
  } catch {
213
- throw new Error('Unable to parse stream transcribe finalize response');
274
+ throw new Error('Unable to parse VAD response');
214
275
  }
215
276
  }
216
277
 
217
- public streamTranscribeDestroy(): Promise<void> {
218
- return this.hybridCactus.streamTranscribeDestroy();
219
- }
220
-
221
278
  public embed(
222
279
  text: string,
223
280
  embeddingBufferSize: number,
@@ -260,4 +317,8 @@ export class Cactus {
260
317
  public destroy(): Promise<void> {
261
318
  return this.hybridCactus.destroy();
262
319
  }
320
+
321
+ public setTelemetryEnvironment(cacheDir: string): Promise<void> {
322
+ return this.hybridCactus.setTelemetryEnvironment(cacheDir);
323
+ }
263
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,11 +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
- streamTranscribeInit(): Promise<void>;
31
- streamTranscribeInsert(audio: number[]): Promise<void>;
32
- streamTranscribeProcess(optionsJson?: string): Promise<string>;
33
- streamTranscribeFinalize(): Promise<string>;
34
- streamTranscribeDestroy(): Promise<void>;
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>;
35
38
  embed(
36
39
  text: string,
37
40
  embeddingBufferSize: number,
@@ -42,4 +45,5 @@ export interface Cactus extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
42
45
  reset(): Promise<void>;
43
46
  stop(): Promise<void>;
44
47
  destroy(): Promise<void>;
48
+ setTelemetryEnvironment(cacheDir: string): Promise<void>;
45
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 {