cactus-react-native 1.5.0 → 1.10.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 (221) 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 +197 -117
  10. package/cpp/HybridCactus.hpp +18 -9
  11. package/cpp/cactus_ffi.h +66 -42
  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_cloud.h +48 -0
  14. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_ffi.h +66 -42
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_utils.h +568 -135
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +148 -17
  17. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +145 -36
  18. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +187 -6
  19. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel_utils.h +49 -149
  20. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Info.plist +0 -0
  21. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  22. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus.h +0 -1
  23. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_cloud.h +48 -0
  24. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +66 -42
  25. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_utils.h +568 -135
  26. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +148 -17
  27. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +145 -36
  28. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +187 -6
  29. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel_utils.h +49 -149
  30. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Info.plist +0 -0
  31. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/_CodeSignature/CodeResources +1 -1
  32. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  33. package/lib/module/classes/CactusLM.js +16 -49
  34. package/lib/module/classes/CactusLM.js.map +1 -1
  35. package/lib/module/classes/CactusSTT.js +41 -75
  36. package/lib/module/classes/CactusSTT.js.map +1 -1
  37. package/lib/module/classes/CactusVAD.js +95 -0
  38. package/lib/module/classes/CactusVAD.js.map +1 -0
  39. package/lib/module/hooks/useCactusLM.js +10 -11
  40. package/lib/module/hooks/useCactusLM.js.map +1 -1
  41. package/lib/module/hooks/useCactusSTT.js +23 -62
  42. package/lib/module/hooks/useCactusSTT.js.map +1 -1
  43. package/lib/module/hooks/useCactusVAD.js +171 -0
  44. package/lib/module/hooks/useCactusVAD.js.map +1 -0
  45. package/lib/module/index.js +2 -3
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/modelRegistry.js +52 -0
  48. package/lib/module/modelRegistry.js.map +1 -0
  49. package/lib/module/native/Cactus.js +103 -23
  50. package/lib/module/native/Cactus.js.map +1 -1
  51. package/lib/module/native/CactusIndex.js.map +1 -1
  52. package/lib/module/native/index.js +0 -3
  53. package/lib/module/native/index.js.map +1 -1
  54. package/lib/module/types/CactusVAD.js +4 -0
  55. package/lib/module/{specs/CactusUtil.nitro.js.map → types/CactusVAD.js.map} +1 -1
  56. package/lib/typescript/src/classes/CactusLM.d.ts +5 -7
  57. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  58. package/lib/typescript/src/classes/CactusSTT.d.ts +9 -12
  59. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -1
  60. package/lib/typescript/src/classes/CactusVAD.d.ts +20 -0
  61. package/lib/typescript/src/classes/CactusVAD.d.ts.map +1 -0
  62. package/lib/typescript/src/hooks/useCactusLM.d.ts +2 -2
  63. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  64. package/lib/typescript/src/hooks/useCactusSTT.d.ts +6 -8
  65. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -1
  66. package/lib/typescript/src/hooks/useCactusVAD.d.ts +15 -0
  67. package/lib/typescript/src/hooks/useCactusVAD.d.ts.map +1 -0
  68. package/lib/typescript/src/index.d.ts +7 -5
  69. package/lib/typescript/src/index.d.ts.map +1 -1
  70. package/lib/typescript/src/modelRegistry.d.ts +5 -0
  71. package/lib/typescript/src/modelRegistry.d.ts.map +1 -0
  72. package/lib/typescript/src/native/Cactus.d.ts +13 -11
  73. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  74. package/lib/typescript/src/native/CactusIndex.d.ts +2 -2
  75. package/lib/typescript/src/native/CactusIndex.d.ts.map +1 -1
  76. package/lib/typescript/src/native/index.d.ts +0 -3
  77. package/lib/typescript/src/native/index.d.ts.map +1 -1
  78. package/lib/typescript/src/specs/Cactus.nitro.d.ts +7 -6
  79. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  80. package/lib/typescript/src/types/CactusIndex.d.ts +2 -2
  81. package/lib/typescript/src/types/CactusIndex.d.ts.map +1 -1
  82. package/lib/typescript/src/types/CactusLM.d.ts +19 -11
  83. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  84. package/lib/typescript/src/types/CactusSTT.d.ts +44 -12
  85. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -1
  86. package/lib/typescript/src/types/CactusVAD.d.ts +34 -0
  87. package/lib/typescript/src/types/CactusVAD.d.ts.map +1 -0
  88. package/lib/typescript/src/types/common.d.ts +1 -6
  89. package/lib/typescript/src/types/common.d.ts.map +1 -1
  90. package/nitro.json +0 -11
  91. package/nitrogen/generated/android/cactus+autolinking.cmake +0 -5
  92. package/nitrogen/generated/android/cactusOnLoad.cpp +0 -30
  93. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +0 -50
  94. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +9 -147
  95. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +0 -13
  96. package/nitrogen/generated/ios/CactusAutolinking.mm +0 -26
  97. package/nitrogen/generated/ios/CactusAutolinking.swift +0 -30
  98. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +5 -4
  99. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +7 -6
  100. package/package.json +3 -3
  101. package/src/classes/CactusLM.ts +18 -65
  102. package/src/classes/CactusSTT.ts +52 -90
  103. package/src/classes/CactusVAD.ts +129 -0
  104. package/src/hooks/useCactusLM.ts +14 -17
  105. package/src/hooks/useCactusSTT.ts +47 -98
  106. package/src/hooks/useCactusVAD.ts +215 -0
  107. package/src/index.tsx +21 -12
  108. package/src/modelRegistry.ts +65 -0
  109. package/src/native/Cactus.ts +131 -38
  110. package/src/native/CactusIndex.ts +2 -2
  111. package/src/native/index.ts +0 -3
  112. package/src/specs/Cactus.nitro.ts +16 -7
  113. package/src/types/CactusIndex.ts +2 -2
  114. package/src/types/CactusLM.ts +19 -11
  115. package/src/types/CactusSTT.ts +47 -13
  116. package/src/types/CactusVAD.ts +39 -0
  117. package/src/types/common.ts +1 -6
  118. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusCrypto.kt +0 -46
  119. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusDeviceInfo.kt +0 -27
  120. package/android/src/main/jniLibs/arm64-v8a/libcactus_util.a +0 -0
  121. package/cpp/HybridCactusUtil.cpp +0 -47
  122. package/cpp/HybridCactusUtil.hpp +0 -27
  123. package/cpp/cactus_util.h +0 -25
  124. package/ios/HybridCactusCrypto.swift +0 -37
  125. package/ios/HybridCactusDeviceInfo.swift +0 -32
  126. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_telemetry.h +0 -656
  127. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_telemetry.h +0 -656
  128. package/ios/cactus_util.xcframework/Info.plist +0 -39
  129. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/cactus_util.h +0 -25
  130. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/database.h +0 -27
  131. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/ios_utils.h +0 -10
  132. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Headers/logging.h +0 -25
  133. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/Info.plist +0 -0
  134. package/ios/cactus_util.xcframework/ios-arm64/cactus_util.framework/cactus_util +0 -0
  135. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/cactus_util.h +0 -25
  136. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/database.h +0 -27
  137. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/ios_utils.h +0 -10
  138. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Headers/logging.h +0 -25
  139. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/Info.plist +0 -0
  140. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/_CodeSignature/CodeResources +0 -135
  141. package/ios/cactus_util.xcframework/ios-arm64-simulator/cactus_util.framework/cactus_util +0 -0
  142. package/lib/module/api/Database.js +0 -45
  143. package/lib/module/api/Database.js.map +0 -1
  144. package/lib/module/api/RemoteLM.js +0 -201
  145. package/lib/module/api/RemoteLM.js.map +0 -1
  146. package/lib/module/config/CactusConfig.js +0 -12
  147. package/lib/module/config/CactusConfig.js.map +0 -1
  148. package/lib/module/models.js +0 -336
  149. package/lib/module/models.js.map +0 -1
  150. package/lib/module/native/CactusCrypto.js +0 -10
  151. package/lib/module/native/CactusCrypto.js.map +0 -1
  152. package/lib/module/native/CactusDeviceInfo.js +0 -13
  153. package/lib/module/native/CactusDeviceInfo.js.map +0 -1
  154. package/lib/module/native/CactusUtil.js +0 -36
  155. package/lib/module/native/CactusUtil.js.map +0 -1
  156. package/lib/module/specs/CactusCrypto.nitro.js +0 -4
  157. package/lib/module/specs/CactusCrypto.nitro.js.map +0 -1
  158. package/lib/module/specs/CactusDeviceInfo.nitro.js +0 -4
  159. package/lib/module/specs/CactusDeviceInfo.nitro.js.map +0 -1
  160. package/lib/module/specs/CactusUtil.nitro.js +0 -4
  161. package/lib/module/telemetry/Telemetry.js +0 -154
  162. package/lib/module/telemetry/Telemetry.js.map +0 -1
  163. package/lib/typescript/src/api/Database.d.ts +0 -12
  164. package/lib/typescript/src/api/Database.d.ts.map +0 -1
  165. package/lib/typescript/src/api/RemoteLM.d.ts +0 -14
  166. package/lib/typescript/src/api/RemoteLM.d.ts.map +0 -1
  167. package/lib/typescript/src/config/CactusConfig.d.ts +0 -7
  168. package/lib/typescript/src/config/CactusConfig.d.ts.map +0 -1
  169. package/lib/typescript/src/models.d.ts +0 -6
  170. package/lib/typescript/src/models.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/nitrogen/generated/android/c++/JDeviceInfo.hpp +0 -74
  186. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.cpp +0 -65
  187. package/nitrogen/generated/android/c++/JHybridCactusCryptoSpec.hpp +0 -65
  188. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.cpp +0 -85
  189. package/nitrogen/generated/android/c++/JHybridCactusDeviceInfoSpec.hpp +0 -66
  190. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/DeviceInfo.kt +0 -50
  191. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusCryptoSpec.kt +0 -58
  192. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusDeviceInfoSpec.kt +0 -62
  193. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.cpp +0 -11
  194. package/nitrogen/generated/ios/c++/HybridCactusCryptoSpecSwift.hpp +0 -77
  195. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.cpp +0 -11
  196. package/nitrogen/generated/ios/c++/HybridCactusDeviceInfoSpecSwift.hpp +0 -88
  197. package/nitrogen/generated/ios/swift/DeviceInfo.swift +0 -98
  198. package/nitrogen/generated/ios/swift/Func_void_DeviceInfo.swift +0 -47
  199. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -54
  200. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec.swift +0 -57
  201. package/nitrogen/generated/ios/swift/HybridCactusCryptoSpec_cxx.swift +0 -139
  202. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec.swift +0 -58
  203. package/nitrogen/generated/ios/swift/HybridCactusDeviceInfoSpec_cxx.swift +0 -164
  204. package/nitrogen/generated/shared/c++/DeviceInfo.hpp +0 -92
  205. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.cpp +0 -21
  206. package/nitrogen/generated/shared/c++/HybridCactusCryptoSpec.hpp +0 -63
  207. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.cpp +0 -22
  208. package/nitrogen/generated/shared/c++/HybridCactusDeviceInfoSpec.hpp +0 -67
  209. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.cpp +0 -23
  210. package/nitrogen/generated/shared/c++/HybridCactusUtilSpec.hpp +0 -66
  211. package/src/api/Database.ts +0 -55
  212. package/src/api/RemoteLM.ts +0 -273
  213. package/src/config/CactusConfig.ts +0 -11
  214. package/src/models.ts +0 -344
  215. package/src/native/CactusCrypto.ts +0 -11
  216. package/src/native/CactusDeviceInfo.ts +0 -18
  217. package/src/native/CactusUtil.ts +0 -43
  218. package/src/specs/CactusCrypto.nitro.ts +0 -6
  219. package/src/specs/CactusDeviceInfo.nitro.ts +0 -15
  220. package/src/specs/CactusUtil.nitro.ts +0 -8
  221. package/src/telemetry/Telemetry.ts +0 -236
@@ -9,23 +9,22 @@ import type {
9
9
  CactusSTTDownloadParams,
10
10
  CactusSTTAudioEmbedParams,
11
11
  CactusSTTAudioEmbedResult,
12
- CactusSTTStreamTranscribeInsertParams,
12
+ CactusSTTStreamTranscribeStartOptions,
13
13
  CactusSTTStreamTranscribeProcessParams,
14
14
  CactusSTTStreamTranscribeProcessResult,
15
- CactusSTTStreamTranscribeFinalizeResult,
15
+ CactusSTTStreamTranscribeStopResult,
16
16
  } from '../types/CactusSTT';
17
17
  import type { CactusModel } from '../types/common';
18
18
 
19
19
  export const useCactusSTT = ({
20
20
  model = 'whisper-small',
21
- contextSize = 2048,
22
21
  options: modelOptions = {
23
22
  quantization: undefined,
24
23
  pro: false,
25
24
  },
26
25
  }: CactusSTTParams = {}) => {
27
26
  const [cactusSTT, setCactusSTT] = useState(
28
- () => new CactusSTT({ model, contextSize, options: modelOptions })
27
+ () => new CactusSTT({ model, options: modelOptions })
29
28
  );
30
29
 
31
30
  // State
@@ -49,16 +48,14 @@ export const useCactusSTT = ({
49
48
  }, [model]);
50
49
 
51
50
  useEffect(() => {
52
- setCactusSTT(
53
- new CactusSTT({
54
- model,
55
- contextSize,
56
- options: {
57
- quantization: modelOptions.quantization,
58
- pro: modelOptions.pro,
59
- },
60
- })
61
- );
51
+ const newInstance = new CactusSTT({
52
+ model,
53
+ options: {
54
+ quantization: modelOptions.quantization,
55
+ pro: modelOptions.pro,
56
+ },
57
+ });
58
+ setCactusSTT(newInstance);
62
59
 
63
60
  setTranscription('');
64
61
  setStreamTranscribeConfirmed('');
@@ -72,25 +69,21 @@ export const useCactusSTT = ({
72
69
  setError(null);
73
70
 
74
71
  let mounted = true;
75
- CactusFileSystem.modelExists(model)
72
+ CactusFileSystem.modelExists(newInstance.getModelName())
76
73
  .then((exists) => {
77
- if (!mounted) {
78
- return;
79
- }
80
- setIsDownloaded(exists);
74
+ if (mounted) setIsDownloaded(exists);
81
75
  })
82
76
  .catch((e) => {
83
- if (!mounted) {
84
- return;
77
+ if (mounted) {
78
+ setIsDownloaded(false);
79
+ setError(getErrorMessage(e));
85
80
  }
86
- setIsDownloaded(false);
87
- setError(getErrorMessage(e));
88
81
  });
89
82
 
90
83
  return () => {
91
84
  mounted = false;
92
85
  };
93
- }, [model, contextSize, modelOptions.quantization, modelOptions.pro]);
86
+ }, [model, modelOptions.quantization, modelOptions.pro]);
94
87
 
95
88
  useEffect(() => {
96
89
  return () => {
@@ -115,49 +108,29 @@ export const useCactusSTT = ({
115
108
  const thisModel = currentModelRef.current;
116
109
  const thisDownloadId = ++currentDownloadIdRef.current;
117
110
 
111
+ const isCurrent = () =>
112
+ currentModelRef.current === thisModel &&
113
+ currentDownloadIdRef.current === thisDownloadId;
114
+
118
115
  setDownloadProgress(0);
119
116
  setIsDownloading(true);
120
117
  try {
121
118
  await cactusSTT.download({
122
119
  onProgress: (progress) => {
123
- if (
124
- currentModelRef.current !== thisModel ||
125
- currentDownloadIdRef.current !== thisDownloadId
126
- ) {
127
- return;
128
- }
129
-
120
+ if (!isCurrent()) return;
130
121
  setDownloadProgress(progress);
131
122
  onProgress?.(progress);
132
123
  },
133
124
  });
134
125
 
135
- if (
136
- currentModelRef.current !== thisModel ||
137
- currentDownloadIdRef.current !== thisDownloadId
138
- ) {
139
- return;
140
- }
141
-
126
+ if (!isCurrent()) return;
142
127
  setIsDownloaded(true);
143
128
  } catch (e) {
144
- if (
145
- currentModelRef.current !== thisModel ||
146
- currentDownloadIdRef.current !== thisDownloadId
147
- ) {
148
- return;
149
- }
150
-
129
+ if (!isCurrent()) return;
151
130
  setError(getErrorMessage(e));
152
131
  throw e;
153
132
  } finally {
154
- if (
155
- currentModelRef.current !== thisModel ||
156
- currentDownloadIdRef.current !== thisDownloadId
157
- ) {
158
- return;
159
- }
160
-
133
+ if (!isCurrent()) return;
161
134
  setIsDownloading(false);
162
135
  setDownloadProgress(0);
163
136
  }
@@ -244,44 +217,34 @@ export const useCactusSTT = ({
244
217
  [cactusSTT, isGenerating]
245
218
  );
246
219
 
247
- const streamTranscribeInit = useCallback(async () => {
248
- if (isStreamTranscribing) {
249
- return;
250
- }
251
-
252
- setError(null);
253
- setStreamTranscribeConfirmed('');
254
- setStreamTranscribePending('');
255
- setIsStreamTranscribing(true);
256
- try {
257
- await cactusSTT.streamTranscribeInit();
258
- } catch (e) {
259
- setError(getErrorMessage(e));
260
- setIsStreamTranscribing(false);
261
- throw e;
262
- }
263
- }, [cactusSTT, isStreamTranscribing]);
220
+ const streamTranscribeStart = useCallback(
221
+ async (options?: CactusSTTStreamTranscribeStartOptions) => {
222
+ if (isStreamTranscribing) {
223
+ return;
224
+ }
264
225
 
265
- const streamTranscribeInsert = useCallback(
266
- async ({ audio }: CactusSTTStreamTranscribeInsertParams): Promise<void> => {
267
226
  setError(null);
227
+ setStreamTranscribeConfirmed('');
228
+ setStreamTranscribePending('');
229
+ setIsStreamTranscribing(true);
268
230
  try {
269
- await cactusSTT.streamTranscribeInsert({ audio });
231
+ await cactusSTT.streamTranscribeStart(options);
270
232
  } catch (e) {
271
233
  setError(getErrorMessage(e));
234
+ setIsStreamTranscribing(false);
272
235
  throw e;
273
236
  }
274
237
  },
275
- [cactusSTT]
238
+ [cactusSTT, isStreamTranscribing]
276
239
  );
277
240
 
278
241
  const streamTranscribeProcess = useCallback(
279
242
  async ({
280
- options,
281
- }: CactusSTTStreamTranscribeProcessParams = {}): Promise<CactusSTTStreamTranscribeProcessResult> => {
243
+ audio,
244
+ }: CactusSTTStreamTranscribeProcessParams): Promise<CactusSTTStreamTranscribeProcessResult> => {
282
245
  setError(null);
283
246
  try {
284
- const result = await cactusSTT.streamTranscribeProcess({ options });
247
+ const result = await cactusSTT.streamTranscribeProcess({ audio });
285
248
  setStreamTranscribeConfirmed((prev) => prev + result.confirmed);
286
249
  setStreamTranscribePending(result.pending);
287
250
  return result;
@@ -293,34 +256,22 @@ export const useCactusSTT = ({
293
256
  [cactusSTT]
294
257
  );
295
258
 
296
- const streamTranscribeFinalize =
297
- useCallback(async (): Promise<CactusSTTStreamTranscribeFinalizeResult> => {
259
+ const streamTranscribeStop =
260
+ useCallback(async (): Promise<CactusSTTStreamTranscribeStopResult> => {
298
261
  setError(null);
299
262
  try {
300
- const result = await cactusSTT.streamTranscribeFinalize();
263
+ const result = await cactusSTT.streamTranscribeStop();
301
264
  setStreamTranscribeConfirmed((prev) => prev + result.confirmed);
302
265
  setStreamTranscribePending('');
303
- setIsStreamTranscribing(false);
304
266
  return result;
305
267
  } catch (e) {
306
268
  setError(getErrorMessage(e));
307
269
  throw e;
270
+ } finally {
271
+ setIsStreamTranscribing(false);
308
272
  }
309
273
  }, [cactusSTT]);
310
274
 
311
- const streamTranscribeDestroy = useCallback(async (): Promise<void> => {
312
- setError(null);
313
- try {
314
- await cactusSTT.streamTranscribeDestroy();
315
- } catch (e) {
316
- setError(getErrorMessage(e));
317
- throw e;
318
- } finally {
319
- setIsStreamTranscribing(false);
320
- setStreamTranscribePending('');
321
- }
322
- }, [cactusSTT]);
323
-
324
275
  const stop = useCallback(async () => {
325
276
  setError(null);
326
277
  try {
@@ -384,13 +335,11 @@ export const useCactusSTT = ({
384
335
  init,
385
336
  transcribe,
386
337
  audioEmbed,
387
- streamTranscribeInit,
388
- streamTranscribeInsert,
338
+ streamTranscribeStart,
389
339
  streamTranscribeProcess,
390
- streamTranscribeFinalize,
391
- streamTranscribeDestroy,
392
- reset,
340
+ streamTranscribeStop,
393
341
  stop,
342
+ reset,
394
343
  destroy,
395
344
  getModels,
396
345
  };
@@ -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,34 @@ 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,
44
+ CactusSTTDetectLanguageOptions,
45
+ CactusSTTDetectLanguageParams,
46
+ CactusSTTDetectLanguageResult,
43
47
  } from './types/CactusSTT';
48
+ export type {
49
+ CactusVADParams,
50
+ CactusVADDownloadParams,
51
+ CactusVADVadParams,
52
+ CactusVADOptions,
53
+ CactusVADSegment,
54
+ CactusVADResult,
55
+ } from './types/CactusVAD';
44
56
  export type {
45
57
  CactusIndexParams,
46
58
  CactusIndexAddParams,
47
59
  CactusIndexGetParams,
48
60
  CactusIndexGetResult,
49
- IndexQueryOptions,
61
+ CactusIndexQueryOptions,
50
62
  CactusIndexQueryParams,
51
63
  CactusIndexQueryResult,
52
64
  CactusIndexDeleteParams,
53
65
  } 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
+ }