cactus-react-native 1.0.2 → 1.2.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 (126) hide show
  1. package/README.md +378 -21
  2. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusCrypto.kt +23 -15
  3. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusDeviceInfo.kt +12 -9
  4. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusFileSystem.kt +42 -41
  5. package/android/src/main/java/com/margelo/nitro/cactus/HybridCactusImage.kt +81 -0
  6. package/android/src/main/jniLibs/arm64-v8a/libcactus.a +0 -0
  7. package/cpp/HybridCactus.cpp +105 -0
  8. package/cpp/HybridCactus.hpp +13 -0
  9. package/cpp/cactus_ffi.h +27 -0
  10. package/ios/HybridCactusImage.swift +53 -0
  11. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/cactus_ffi.h +27 -0
  12. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/engine.h +37 -5
  13. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/ffi_utils.h +10 -9
  14. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/graph.h +49 -7
  15. package/ios/cactus.xcframework/ios-arm64/cactus.framework/Headers/kernel.h +31 -0
  16. package/ios/cactus.xcframework/ios-arm64/cactus.framework/cactus +0 -0
  17. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/cactus_ffi.h +27 -0
  18. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/engine.h +37 -5
  19. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/ffi_utils.h +10 -9
  20. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/graph.h +49 -7
  21. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/Headers/kernel.h +31 -0
  22. package/ios/cactus.xcframework/ios-arm64-simulator/cactus.framework/cactus +0 -0
  23. package/lib/module/api/Database.js +23 -0
  24. package/lib/module/api/Database.js.map +1 -1
  25. package/lib/module/api/RemoteLM.js +201 -0
  26. package/lib/module/api/RemoteLM.js.map +1 -0
  27. package/lib/module/classes/CactusLM.js +52 -26
  28. package/lib/module/classes/CactusLM.js.map +1 -1
  29. package/lib/module/classes/CactusSTT.js +139 -0
  30. package/lib/module/classes/CactusSTT.js.map +1 -0
  31. package/lib/module/config/CactusConfig.js +4 -0
  32. package/lib/module/config/CactusConfig.js.map +1 -1
  33. package/lib/module/constants/packageVersion.js +1 -1
  34. package/lib/module/hooks/useCactusLM.js +33 -10
  35. package/lib/module/hooks/useCactusLM.js.map +1 -1
  36. package/lib/module/hooks/useCactusSTT.js +234 -0
  37. package/lib/module/hooks/useCactusSTT.js.map +1 -0
  38. package/lib/module/index.js +2 -0
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/native/Cactus.js +50 -1
  41. package/lib/module/native/Cactus.js.map +1 -1
  42. package/lib/module/native/CactusFileSystem.js +2 -3
  43. package/lib/module/native/CactusFileSystem.js.map +1 -1
  44. package/lib/module/native/CactusImage.js +13 -0
  45. package/lib/module/native/CactusImage.js.map +1 -0
  46. package/lib/module/native/index.js +1 -0
  47. package/lib/module/native/index.js.map +1 -1
  48. package/lib/module/specs/CactusImage.nitro.js +4 -0
  49. package/lib/module/specs/CactusImage.nitro.js.map +1 -0
  50. package/lib/module/telemetry/Telemetry.js +53 -1
  51. package/lib/module/telemetry/Telemetry.js.map +1 -1
  52. package/lib/module/types/CactusSTT.js +2 -0
  53. package/lib/module/types/CactusSTT.js.map +1 -0
  54. package/lib/typescript/src/api/Database.d.ts +1 -0
  55. package/lib/typescript/src/api/Database.d.ts.map +1 -1
  56. package/lib/typescript/src/api/RemoteLM.d.ts +14 -0
  57. package/lib/typescript/src/api/RemoteLM.d.ts.map +1 -0
  58. package/lib/typescript/src/classes/CactusLM.d.ts +6 -4
  59. package/lib/typescript/src/classes/CactusLM.d.ts.map +1 -1
  60. package/lib/typescript/src/classes/CactusSTT.d.ts +26 -0
  61. package/lib/typescript/src/classes/CactusSTT.d.ts.map +1 -0
  62. package/lib/typescript/src/config/CactusConfig.d.ts +1 -0
  63. package/lib/typescript/src/config/CactusConfig.d.ts.map +1 -1
  64. package/lib/typescript/src/constants/packageVersion.d.ts +1 -1
  65. package/lib/typescript/src/hooks/useCactusLM.d.ts +4 -3
  66. package/lib/typescript/src/hooks/useCactusLM.d.ts.map +1 -1
  67. package/lib/typescript/src/hooks/useCactusSTT.d.ts +20 -0
  68. package/lib/typescript/src/hooks/useCactusSTT.d.ts.map +1 -0
  69. package/lib/typescript/src/index.d.ts +4 -1
  70. package/lib/typescript/src/index.d.ts.map +1 -1
  71. package/lib/typescript/src/native/Cactus.d.ts +9 -2
  72. package/lib/typescript/src/native/Cactus.d.ts.map +1 -1
  73. package/lib/typescript/src/native/CactusFileSystem.d.ts +1 -1
  74. package/lib/typescript/src/native/CactusFileSystem.d.ts.map +1 -1
  75. package/lib/typescript/src/native/CactusImage.d.ts +6 -0
  76. package/lib/typescript/src/native/CactusImage.d.ts.map +1 -0
  77. package/lib/typescript/src/native/index.d.ts +1 -0
  78. package/lib/typescript/src/native/index.d.ts.map +1 -1
  79. package/lib/typescript/src/specs/Cactus.nitro.d.ts +3 -0
  80. package/lib/typescript/src/specs/Cactus.nitro.d.ts.map +1 -1
  81. package/lib/typescript/src/specs/CactusImage.nitro.d.ts +9 -0
  82. package/lib/typescript/src/specs/CactusImage.nitro.d.ts.map +1 -0
  83. package/lib/typescript/src/telemetry/Telemetry.d.ts +5 -1
  84. package/lib/typescript/src/telemetry/Telemetry.d.ts.map +1 -1
  85. package/lib/typescript/src/types/CactusLM.d.ts +8 -5
  86. package/lib/typescript/src/types/CactusLM.d.ts.map +1 -1
  87. package/lib/typescript/src/types/CactusSTT.d.ts +37 -0
  88. package/lib/typescript/src/types/CactusSTT.d.ts.map +1 -0
  89. package/nitro.json +4 -0
  90. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.cpp +81 -0
  91. package/nitrogen/generated/android/c++/JHybridCactusImageSpec.hpp +66 -0
  92. package/nitrogen/generated/android/cactus+autolinking.cmake +2 -0
  93. package/nitrogen/generated/android/cactusOnLoad.cpp +10 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/cactus/HybridCactusImageSpec.kt +62 -0
  95. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.cpp +17 -0
  96. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Bridge.hpp +17 -0
  97. package/nitrogen/generated/ios/Cactus-Swift-Cxx-Umbrella.hpp +5 -0
  98. package/nitrogen/generated/ios/CactusAutolinking.mm +8 -0
  99. package/nitrogen/generated/ios/CactusAutolinking.swift +15 -0
  100. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.cpp +11 -0
  101. package/nitrogen/generated/ios/c++/HybridCactusImageSpecSwift.hpp +85 -0
  102. package/nitrogen/generated/ios/swift/HybridCactusImageSpec.swift +58 -0
  103. package/nitrogen/generated/ios/swift/HybridCactusImageSpec_cxx.swift +158 -0
  104. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.cpp +22 -0
  105. package/nitrogen/generated/shared/c++/HybridCactusImageSpec.hpp +64 -0
  106. package/nitrogen/generated/shared/c++/HybridCactusSpec.cpp +3 -0
  107. package/nitrogen/generated/shared/c++/HybridCactusSpec.hpp +3 -0
  108. package/package.json +1 -1
  109. package/src/api/Database.ts +27 -0
  110. package/src/api/RemoteLM.ts +273 -0
  111. package/src/classes/CactusLM.ts +72 -38
  112. package/src/classes/CactusSTT.ts +188 -0
  113. package/src/config/CactusConfig.ts +4 -0
  114. package/src/constants/packageVersion.ts +1 -1
  115. package/src/hooks/useCactusLM.ts +45 -17
  116. package/src/hooks/useCactusSTT.ts +285 -0
  117. package/src/index.tsx +14 -2
  118. package/src/native/Cactus.ts +94 -4
  119. package/src/native/CactusFileSystem.ts +2 -2
  120. package/src/native/CactusImage.ts +20 -0
  121. package/src/native/index.ts +1 -0
  122. package/src/specs/Cactus.nitro.ts +9 -0
  123. package/src/specs/CactusImage.nitro.ts +12 -0
  124. package/src/telemetry/Telemetry.ts +78 -1
  125. package/src/types/CactusLM.ts +9 -5
  126. package/src/types/CactusSTT.ts +42 -0
package/README.md CHANGED
@@ -185,7 +185,6 @@ import { CactusLM, type Message, type Tool } from 'cactus-react-native';
185
185
 
186
186
  const tools: Tool[] = [
187
187
  {
188
- type: 'function',
189
188
  name: 'get_weather',
190
189
  description: 'Get current weather for a location',
191
190
  parameters: {
@@ -219,7 +218,6 @@ import { useCactusLM, type Message, type Tool } from 'cactus-react-native';
219
218
 
220
219
  const tools: Tool[] = [
221
220
  {
222
- type: 'function',
223
221
  name: 'get_weather',
224
222
  description: 'Get current weather for a location',
225
223
  parameters: {
@@ -302,9 +300,11 @@ const App = () => {
302
300
 
303
301
  ### Embedding
304
302
 
305
- Convert text into numerical vector representations that capture semantic meaning, useful for similarity search and semantic understanding.
303
+ Convert text and images into numerical vector representations that capture semantic meaning, useful for similarity search and semantic understanding.
306
304
 
307
- #### Class
305
+ #### Text Embedding
306
+
307
+ ##### Class
308
308
 
309
309
  ```typescript
310
310
  import { CactusLM } from 'cactus-react-native';
@@ -316,7 +316,7 @@ console.log('Embedding vector:', result.embedding);
316
316
  console.log('Embedding vector length:', result.embedding.length);
317
317
  ```
318
318
 
319
- #### Hook
319
+ ##### Hook
320
320
 
321
321
  ```tsx
322
322
  import { useCactusLM } from 'cactus-react-native';
@@ -334,6 +334,179 @@ const App = () => {
334
334
  };
335
335
  ```
336
336
 
337
+ #### Image Embedding
338
+
339
+ ##### Class
340
+
341
+ ```typescript
342
+ import { CactusLM } from 'cactus-react-native';
343
+
344
+ const cactusLM = new CactusLM({ model: 'lfm2-vl-450m' });
345
+
346
+ const result = await cactusLM.imageEmbed({ imagePath: 'path/to/your/image.jpg' });
347
+ console.log('Image embedding vector:', result.embedding);
348
+ console.log('Embedding vector length:', result.embedding.length);
349
+ ```
350
+
351
+ ##### Hook
352
+
353
+ ```tsx
354
+ import { useCactusLM } from 'cactus-react-native';
355
+
356
+ const App = () => {
357
+ const cactusLM = useCactusLM({ model: 'lfm2-vl-450m' });
358
+
359
+ const handleImageEmbed = async () => {
360
+ const result = await cactusLM.imageEmbed({ imagePath: 'path/to/your/image.jpg' });
361
+ console.log('Image embedding vector:', result.embedding);
362
+ console.log('Embedding vector length:', result.embedding.length);
363
+ };
364
+
365
+ return <Button title="Embed Image" onPress={handleImageEmbed} />;
366
+ };
367
+ ```
368
+
369
+ ### Hybrid Mode (Cloud Fallback)
370
+
371
+ The CactusLM supports a hybrid completion mode that falls back to a cloud-based LLM provider `OpenRouter` if local inference fails.
372
+
373
+ #### Class
374
+
375
+ ```typescript
376
+ import { CactusLM, type Message } from 'cactus-react-native';
377
+
378
+ const cactusLM = new CactusLM();
379
+
380
+ const messages: Message[] = [
381
+ { role: 'user', content: 'Hello, World!' }
382
+ ];
383
+
384
+ // Falls back to remote if local fails
385
+ const result = await cactusLM.complete({
386
+ messages,
387
+ mode: 'hybrid'
388
+ });
389
+ ```
390
+
391
+ #### Hook
392
+
393
+ ```tsx
394
+ import { useCactusLM, type Message } from 'cactus-react-native';
395
+
396
+ const App = () => {
397
+ const cactusLM = useCactusLM();
398
+
399
+ const handleComplete = async () => {
400
+ const messages: Message[] = [
401
+ { role: 'user', content: 'Hello, World!' }
402
+ ];
403
+
404
+ // Falls back to remote if local fails
405
+ await cactusLM.complete({
406
+ messages,
407
+ mode: 'hybrid'
408
+ });
409
+ };
410
+
411
+ return (
412
+ <>
413
+ <Button title="Complete" onPress={handleComplete} />
414
+ <Text>{cactusLM.completion}</Text>
415
+ </>
416
+ );
417
+ };
418
+ ```
419
+
420
+ ## Speech-to-Text (STT)
421
+
422
+ The `CactusSTT` class provides audio transcription and audio embedding capabilities using Whisper models.
423
+
424
+ ### Transcription
425
+
426
+ Transcribe audio files to text with streaming support.
427
+
428
+ #### Class
429
+
430
+ ```typescript
431
+ import { CactusSTT } from 'cactus-react-native';
432
+
433
+ const cactusSTT = new CactusSTT({ model: 'whisper-small' });
434
+
435
+ await cactusSTT.init();
436
+
437
+ const result = await cactusSTT.transcribe({
438
+ audioFilePath: 'path/to/audio.wav',
439
+ onToken: (token) => console.log('Token:', token)
440
+ });
441
+
442
+ console.log('Transcription:', result.response);
443
+ ```
444
+
445
+ #### Hook
446
+
447
+ ```tsx
448
+ import { useCactusSTT } from 'cactus-react-native';
449
+
450
+ const App = () => {
451
+ const cactusSTT = useCactusSTT({ model: 'whisper-small' });
452
+
453
+ const handleTranscribe = async () => {
454
+ const result = await cactusSTT.transcribe({
455
+ audioFilePath: 'path/to/audio.wav',
456
+ });
457
+ console.log('Transcription:', result.response);
458
+ };
459
+
460
+ return (
461
+ <>
462
+ <Button onPress={handleTranscribe} title="Transcribe" />
463
+ <Text>{cactusSTT.transcription}</Text>
464
+ </>
465
+ );
466
+ };
467
+ ```
468
+
469
+ ### Audio Embedding
470
+
471
+ Generate embeddings from audio files for audio understanding.
472
+
473
+ #### Class
474
+
475
+ ```typescript
476
+ import { CactusSTT } from 'cactus-react-native';
477
+
478
+ const cactusSTT = new CactusSTT();
479
+
480
+ await cactusSTT.init();
481
+
482
+ const result = await cactusSTT.audioEmbed({
483
+ audioPath: 'path/to/audio.wav'
484
+ });
485
+
486
+ console.log('Audio embedding vector:', result.embedding);
487
+ console.log('Embedding vector length:', result.embedding.length);
488
+ ```
489
+
490
+ #### Hook
491
+
492
+ ```tsx
493
+ import { useCactusSTT } from 'cactus-react-native';
494
+
495
+ const App = () => {
496
+ const cactusSTT = useCactusSTT();
497
+
498
+ const handleAudioEmbed = async () => {
499
+ const result = await cactusSTT.audioEmbed({
500
+ audioPath: 'path/to/audio.wav'
501
+ });
502
+ console.log('Audio embedding vector:', result.embedding);
503
+ console.log('Embedding vector length:', result.embedding.length);
504
+ };
505
+
506
+ return <Button title="Embed Audio" onPress={handleAudioEmbed} />;
507
+ };
508
+ ```
509
+
337
510
  ## API Reference
338
511
 
339
512
  ### CactusLM Class
@@ -351,14 +524,14 @@ const App = () => {
351
524
 
352
525
  **`download(params?: CactusLMDownloadParams): Promise<void>`**
353
526
 
354
- Downloads the model. If the model is already downloaded, returns immediately with progress at 100%. Throws an error if a download is already in progress. Automatically refreshes the models list after successful download.
527
+ Downloads the model. If the model is already downloaded, returns immediately with progress `1`. Throws an error if a download is already in progress.
355
528
 
356
529
  **Parameters:**
357
530
  - `onProgress` - Callback for download progress (0-1).
358
531
 
359
532
  **`init(): Promise<void>`**
360
533
 
361
- Initializes the model and prepares it for inference. Safe to call multiple times (idempotent). Throws an error if the model is not downloaded yet. Automatically initializes telemetry if not already done.
534
+ Initializes the model and prepares it for inference. Safe to call multiple times (idempotent). Throws an error if the model is not downloaded yet.
362
535
 
363
536
  **`complete(params: CactusLMCompleteParams): Promise<CactusLMCompleteResult>`**
364
537
 
@@ -374,6 +547,7 @@ Performs text completion with optional streaming and tool support. Automatically
374
547
  - `stopSequences` - Array of strings to stop generation (default: `undefined`).
375
548
  - `tools` - Array of `Tool` objects for function calling (default: `undefined`).
376
549
  - `onToken` - Callback for streaming tokens.
550
+ - `mode` - Completion mode: `'local'` | `'hybrid'` (default: `'local'`)
377
551
 
378
552
  **`embed(params: CactusLMEmbedParams): Promise<CactusLMEmbedResult>`**
379
553
 
@@ -382,6 +556,13 @@ Generates embeddings for the given text. Automatically calls `init()` if not alr
382
556
  **Parameters:**
383
557
  - `text` - Text to embed.
384
558
 
559
+ **`imageEmbed(params: CactusLMImageEmbedParams): Promise<CactusLMImageEmbedResult>`**
560
+
561
+ Generates embeddings for the given image. Requires a vision-capable model. Automatically calls `init()` if not already initialized. Throws an error if a generation (completion or embedding) is already in progress.
562
+
563
+ **Parameters:**
564
+ - `imagePath` - Path to the image file.
565
+
385
566
  **`stop(): Promise<void>`**
386
567
 
387
568
  Stops ongoing generation.
@@ -394,12 +575,9 @@ Resets the model's internal state, clearing any cached context. Automatically ca
394
575
 
395
576
  Releases all resources associated with the model. Automatically calls `stop()` first. Safe to call even if the model is not initialized.
396
577
 
397
- **`getModels(params?: CactusLMGetModelsParams): Promise<CactusModel[]>`**
398
-
399
- Fetches available models and persists the results locally for caching. Returns cached results if available, unless `forceRefresh` is `true`. Checks the download status for each model and includes it in the results.
578
+ **`getModels(): Promise<CactusModel[]>`**
400
579
 
401
- **Parameters:**
402
- - `forceRefresh` - If `true`, fetches from the server and updates the local cache (default: `false`).
580
+ Fetches available models from the database and checks their download status. Results are cached in memory after the first call and subsequent calls return the cached results.
403
581
 
404
582
  ### useCactusLM Hook
405
583
 
@@ -421,10 +599,97 @@ The `useCactusLM` hook manages a `CactusLM` instance with reactive state. When m
421
599
  - `init(): Promise<void>` - Initializes the model for inference. Sets `isInitializing` to `true` during initialization.
422
600
  - `complete(params: CactusLMCompleteParams): Promise<CactusLMCompleteResult>` - Generates text completions. Automatically accumulates tokens in the `completion` state during streaming. Sets `isGenerating` to `true` while generating. Clears `completion` before starting.
423
601
  - `embed(params: CactusLMEmbedParams): Promise<CactusLMEmbedResult>` - Generates embeddings for the given text. Sets `isGenerating` to `true` during operation.
602
+ - `imageEmbed(params: CactusLMImageEmbedParams): Promise<CactusLMImageEmbedResult>` - Generates embeddings for the given image. Sets `isGenerating` to `true` while generating.
424
603
  - `stop(): Promise<void>` - Stops ongoing generation. Clears any errors.
425
604
  - `reset(): Promise<void>` - Resets the model's internal state, clearing cached context. Also clears the `completion` state.
426
605
  - `destroy(): Promise<void>` - Releases all resources associated with the model. Clears the `completion` state. Automatically called when the component unmounts.
427
- - `getModels(params?: CactusLMGetModelsParams): Promise<CactusModel[]>` - Fetches available models and returns them. Results are cached locally.
606
+ - `getModels(): Promise<CactusModel[]>` - Fetches available models from the database and checks their download status. Results are cached in memory and reused on subsequent calls.
607
+
608
+ ### CactusSTT Class
609
+
610
+ #### Constructor
611
+
612
+ **`new CactusSTT(params?: CactusSTTParams)`**
613
+
614
+ **Parameters:**
615
+ - `model` - Model slug (default: `'whisper-small'`).
616
+ - `contextSize` - Context window size (default: `2048`).
617
+
618
+ #### Methods
619
+
620
+ **`download(params?: CactusSTTDownloadParams): Promise<void>`**
621
+
622
+ Downloads the model. If the model is already downloaded, returns immediately with progress `1`. Throws an error if a download is already in progress.
623
+
624
+ **Parameters:**
625
+ - `onProgress` - Callback for download progress (0-1).
626
+
627
+ **`init(): Promise<void>`**
628
+
629
+ Initializes the model and prepares it for inference. Safe to call multiple times (idempotent). Throws an error if the model is not downloaded yet.
630
+
631
+ **`transcribe(params: CactusSTTTranscribeParams): Promise<CactusSTTTranscribeResult>`**
632
+
633
+ Transcribes audio to text with optional streaming support. Automatically calls `init()` if not already initialized. Throws an error if a generation is already in progress.
634
+
635
+ **Parameters:**
636
+ - `audioFilePath` - Path to the audio file.
637
+ - `prompt` - Optional prompt to guide transcription (default: `'<|startoftranscript|><|en|><|transcribe|><|notimestamps|>'`).
638
+ - `options` - Transcription options:
639
+ - `temperature` - Sampling temperature (default: model-optimized).
640
+ - `topP` - Nucleus sampling threshold (default: model-optimized).
641
+ - `topK` - Top-K sampling limit (default: model-optimized).
642
+ - `maxTokens` - Maximum number of tokens to generate (default: `512`).
643
+ - `stopSequences` - Array of strings to stop generation (default: `undefined`).
644
+ - `onToken` - Callback for streaming tokens.
645
+
646
+ **`audioEmbed(params: CactusSTTAudioEmbedParams): Promise<CactusSTTAudioEmbedResult>`**
647
+
648
+ Generates embeddings for the given audio file. Automatically calls `init()` if not already initialized. Throws an error if a generation is already in progress.
649
+
650
+ **Parameters:**
651
+ - `audioPath` - Path to the audio file.
652
+
653
+ **`stop(): Promise<void>`**
654
+
655
+ Stops ongoing transcription or embedding generation.
656
+
657
+ **`reset(): Promise<void>`**
658
+
659
+ Resets the model's internal state. Automatically calls `stop()` first.
660
+
661
+ **`destroy(): Promise<void>`**
662
+
663
+ Releases all resources associated with the model. Automatically calls `stop()` first. Safe to call even if the model is not initialized.
664
+
665
+ **`getModels(): Promise<CactusModel[]>`**
666
+
667
+ Fetches available models from the database and checks their download status. Results are cached in memory after the first call and subsequent calls return the cached results.
668
+
669
+ ### useCactusSTT Hook
670
+
671
+ The `useCactusSTT` hook manages a `CactusSTT` instance with reactive state. When model parameters (`model`, `contextSize`) change, the hook creates a new instance and resets all state. The hook automatically cleans up resources when the component unmounts.
672
+
673
+ #### State
674
+
675
+ - `transcription: string` - Current transcription text. Automatically accumulated during streaming. Cleared before each new transcription and when calling `reset()` or `destroy()`.
676
+ - `isGenerating: boolean` - Whether the model is currently generating (transcription or embedding). Both operations share this flag.
677
+ - `isInitializing: boolean` - Whether the model is initializing.
678
+ - `isDownloaded: boolean` - Whether the model is downloaded locally. Automatically checked when the hook mounts or model changes.
679
+ - `isDownloading: boolean` - Whether the model is being downloaded.
680
+ - `downloadProgress: number` - Download progress (0-1). Reset to `0` after download completes.
681
+ - `error: string | null` - Last error message from any operation, or `null` if there is no error. Cleared before starting new operations.
682
+
683
+ #### Methods
684
+
685
+ - `download(params?: CactusSTTDownloadParams): Promise<void>` - Downloads the model. Updates `isDownloading` and `downloadProgress` state during download. Sets `isDownloaded` to `true` on success.
686
+ - `init(): Promise<void>` - Initializes the model for inference. Sets `isInitializing` to `true` during initialization.
687
+ - `transcribe(params: CactusSTTTranscribeParams): Promise<CactusSTTTranscribeResult>` - Transcribes audio to text. Automatically accumulates tokens in the `transcription` state during streaming. Sets `isGenerating` to `true` while generating. Clears `transcription` before starting.
688
+ - `audioEmbed(params: CactusSTTAudioEmbedParams): Promise<CactusSTTAudioEmbedResult>` - Generates embeddings for the given audio. Sets `isGenerating` to `true` during operation.
689
+ - `stop(): Promise<void>` - Stops ongoing generation. Clears any errors.
690
+ - `reset(): Promise<void>` - Resets the model's internal state. Also clears the `transcription` state.
691
+ - `destroy(): Promise<void>` - Releases all resources associated with the model. Clears the `transcription` state. Automatically called when the component unmounts.
692
+ - `getModels(): Promise<CactusModel[]>` - Fetches available models from the database and checks their download status. Results are cached in memory and reused on subsequent calls.
428
693
 
429
694
  ## Type Definitions
430
695
 
@@ -456,10 +721,10 @@ interface Message {
456
721
  }
457
722
  ```
458
723
 
459
- ### Options
724
+ ### CompleteOptions
460
725
 
461
726
  ```typescript
462
- interface Options {
727
+ interface CompleteOptions {
463
728
  temperature?: number;
464
729
  topP?: number;
465
730
  topK?: number;
@@ -472,7 +737,6 @@ interface Options {
472
737
 
473
738
  ```typescript
474
739
  interface Tool {
475
- type: 'function';
476
740
  name: string;
477
741
  description: string;
478
742
  parameters: {
@@ -493,9 +757,10 @@ interface Tool {
493
757
  ```typescript
494
758
  interface CactusLMCompleteParams {
495
759
  messages: Message[];
496
- options?: Options;
760
+ options?: CompleteOptions;
497
761
  tools?: Tool[];
498
762
  onToken?: (token: string) => void;
763
+ mode?: 'local' | 'hybrid';
499
764
  }
500
765
  ```
501
766
 
@@ -534,11 +799,19 @@ interface CactusLMEmbedResult {
534
799
  }
535
800
  ```
536
801
 
537
- ### CactusLMGetModelsParams
802
+ ### CactusLMImageEmbedParams
803
+
804
+ ```typescript
805
+ interface CactusLMImageEmbedParams {
806
+ imagePath: string;
807
+ }
808
+ ```
809
+
810
+ ### CactusLMImageEmbedResult
538
811
 
539
812
  ```typescript
540
- interface CactusLMGetModelsParams {
541
- forceRefresh?: boolean;
813
+ interface CactusLMImageEmbedResult {
814
+ embedding: number[];
542
815
  }
543
816
  ```
544
817
 
@@ -558,6 +831,79 @@ interface CactusModel {
558
831
  }
559
832
  ```
560
833
 
834
+ ### CactusSTTParams
835
+
836
+ ```typescript
837
+ interface CactusSTTParams {
838
+ model?: string;
839
+ contextSize?: number;
840
+ }
841
+ ```
842
+
843
+ ### CactusSTTDownloadParams
844
+
845
+ ```typescript
846
+ interface CactusSTTDownloadParams {
847
+ onProgress?: (progress: number) => void;
848
+ }
849
+
850
+ ```
851
+
852
+ ### TranscribeOptions
853
+
854
+ ```ts
855
+ interface TranscribeOptions {
856
+ temperature?: number;
857
+ topP?: number;
858
+ topK?: number;
859
+ maxTokens?: number;
860
+ stopSequences?: string[];
861
+ }
862
+ ```
863
+
864
+ ### CactusSTTTranscribeParams
865
+
866
+ ```typescript
867
+ interface CactusSTTTranscribeParams {
868
+ audioFilePath: string;
869
+ prompt?: string;
870
+ options?: TranscribeOptions;
871
+ onToken?: (token: string) => void;
872
+ }
873
+ ```
874
+
875
+ ### CactusSTTTranscribeResult
876
+
877
+ ```typescript
878
+ interface CactusSTTTranscribeResult {
879
+ success: boolean;
880
+ response: string;
881
+ timeToFirstTokenMs: number;
882
+ totalTimeMs: number;
883
+ tokensPerSecond: number;
884
+ prefillTokens: number;
885
+ decodeTokens: number;
886
+ totalTokens: number;
887
+ }
888
+
889
+ ```
890
+
891
+ ### CactusSTTAudioEmbedParams
892
+
893
+ ```typescript
894
+ interface CactusSTTAudioEmbedParams {
895
+ audioPath: string;
896
+ }
897
+ ```
898
+
899
+ ### CactusSTTAudioEmbedResult
900
+
901
+ ```typescript
902
+ interface CactusSTTAudioEmbedResult {
903
+ embedding: number[];
904
+ }
905
+ ```
906
+
561
907
  ## Configuration
562
908
 
563
909
  ### Telemetry
@@ -568,12 +914,23 @@ Cactus offers powerful telemetry for all your projects. Create a token on the [C
568
914
  import { CactusConfig } from 'cactus-react-native';
569
915
 
570
916
  // Enable Telemetry for your project
571
- CactusConfig.telemetryToken = 'your-token-here';
917
+ CactusConfig.telemetryToken = 'your-telemetry-token-here';
572
918
 
573
919
  // Disable telemetry
574
920
  CactusConfig.isTelemetryEnabled = false;
575
921
  ```
576
922
 
923
+ ### Hybrid Mode
924
+
925
+ Enable cloud fallback.
926
+
927
+ ```typescript
928
+ import { CactusConfig } from 'cactus-react-native';
929
+
930
+ // Set your Cactus token for hybrid mode
931
+ CactusConfig.cactusToken = 'your-cactus-token-here';
932
+ ```
933
+
577
934
  ## Performance Tips
578
935
 
579
936
  - **Model Selection** - Choose smaller models for faster inference on mobile devices.
@@ -7,23 +7,32 @@ import java.util.Locale
7
7
  import java.util.UUID
8
8
 
9
9
  class HybridCactusCrypto : HybridCactusCryptoSpec() {
10
- override fun uuidv5(namespaceUuid: String, name: String): Promise<String> {
11
- return Promise.async {
12
- val nsUuid = try {
13
- UUID.fromString(namespaceUuid)
14
- } catch (e: IllegalArgumentException) {
15
- throw IllegalArgumentException("Invalid namespace UUID")
16
- }
10
+ override fun uuidv5(
11
+ namespaceUuid: String,
12
+ name: String,
13
+ ): Promise<String> =
14
+ Promise.async {
15
+ val nsUuid =
16
+ try {
17
+ UUID.fromString(namespaceUuid)
18
+ } catch (e: IllegalArgumentException) {
19
+ throw IllegalArgumentException("Invalid namespace UUID")
20
+ }
17
21
 
18
- val nsBytes = ByteBuffer.allocate(16).apply {
19
- putLong(nsUuid.mostSignificantBits)
20
- putLong(nsUuid.leastSignificantBits)
21
- }.array()
22
+ val nsBytes =
23
+ ByteBuffer
24
+ .allocate(16)
25
+ .apply {
26
+ putLong(nsUuid.mostSignificantBits)
27
+ putLong(nsUuid.leastSignificantBits)
28
+ }.array()
22
29
  val nameBytes = name.toByteArray(Charsets.UTF_8)
23
30
 
24
- val sha1 = MessageDigest.getInstance("SHA-1")
25
- .apply { update(nsBytes) }
26
- .digest(nameBytes)
31
+ val sha1 =
32
+ MessageDigest
33
+ .getInstance("SHA-1")
34
+ .apply { update(nsBytes) }
35
+ .digest(nameBytes)
27
36
  val uuidBytes = sha1.copyOfRange(0, 16)
28
37
  uuidBytes[6] = (uuidBytes[6].toInt() and 0x0F or 0x50).toByte()
29
38
  uuidBytes[8] = (uuidBytes[8].toInt() and 0x3F or 0x80).toByte()
@@ -34,5 +43,4 @@ class HybridCactusCrypto : HybridCactusCryptoSpec() {
34
43
 
35
44
  uuid.toString().lowercase(Locale.ROOT)
36
45
  }
37
- }
38
46
  }
@@ -8,17 +8,20 @@ import com.margelo.nitro.core.Promise
8
8
  class HybridCactusDeviceInfo : HybridCactusDeviceInfoSpec() {
9
9
  private val context = NitroModules.applicationContext ?: error("Android context not found")
10
10
 
11
- override fun getAppIdentifier(): Promise<String?> {
12
- return Promise.async { context.packageName }
13
- }
11
+ override fun getAppIdentifier(): Promise<String?> = Promise.async { context.packageName }
14
12
 
15
- override fun getDeviceInfo(): Promise<DeviceInfo> {
16
- return Promise.async {
13
+ override fun getDeviceInfo(): Promise<DeviceInfo> =
14
+ Promise.async {
17
15
  DeviceInfo(
18
- brand = Build.MANUFACTURER, model = Build.MODEL, device_id = Settings.Secure.getString(
19
- context.contentResolver, Settings.Secure.ANDROID_ID
20
- ), os = "Android", os_version = Build.VERSION.RELEASE
16
+ brand = Build.MANUFACTURER,
17
+ model = Build.MODEL,
18
+ device_id =
19
+ Settings.Secure.getString(
20
+ context.contentResolver,
21
+ Settings.Secure.ANDROID_ID,
22
+ ),
23
+ os = "Android",
24
+ os_version = Build.VERSION.RELEASE,
21
25
  )
22
26
  }
23
- }
24
27
  }