@runanywhere/core 0.17.7 → 0.18.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.
- package/README.md +218 -2
- package/RunAnywhereCore.podspec +1 -0
- package/android/CMakeLists.txt +24 -2
- package/android/build.gradle +61 -9
- package/android/src/main/cpp/cpp-adapter.cpp +51 -3
- package/android/src/main/include/rac/backends/rac_vlm_llamacpp.h +216 -0
- package/android/src/main/include/rac/core/capabilities/rac_lifecycle.h +3 -1
- package/android/src/main/include/rac/core/rac_core.h +11 -0
- package/android/src/main/include/rac/core/rac_types.h +8 -6
- package/android/src/main/include/rac/features/diffusion/rac_diffusion.h +22 -0
- package/android/src/main/include/rac/features/diffusion/rac_diffusion_component.h +263 -0
- package/android/src/main/include/rac/features/diffusion/rac_diffusion_model_registry.h +358 -0
- package/android/src/main/include/rac/features/diffusion/rac_diffusion_service.h +187 -0
- package/android/src/main/include/rac/features/diffusion/rac_diffusion_tokenizer.h +167 -0
- package/android/src/main/include/rac/features/diffusion/rac_diffusion_types.h +454 -0
- package/android/src/main/include/rac/features/llm/rac_tool_calling.h +373 -0
- package/android/src/main/include/rac/features/platform/rac_diffusion_platform.h +305 -0
- package/android/src/main/include/rac/features/vad/rac_vad_energy.h +1 -1
- package/android/src/main/include/rac/features/vlm/rac_vlm.h +16 -0
- package/android/src/main/include/rac/features/vlm/rac_vlm_component.h +168 -0
- package/android/src/main/include/rac/features/vlm/rac_vlm_service.h +206 -0
- package/android/src/main/include/rac/features/vlm/rac_vlm_types.h +417 -0
- package/android/src/main/include/rac/infrastructure/model_management/rac_model_registry.h +15 -0
- package/android/src/main/include/rac/infrastructure/model_management/rac_model_types.h +3 -0
- package/android/src/main/include/rac/utils/rac_image_utils.h +215 -0
- package/android/src/main/java/com/margelo/nitro/runanywhere/PlatformAdapterBridge.kt +201 -1
- package/android/src/main/jniLibs/arm64-v8a/libc++_shared.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libomp.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/librac_commons.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/librunanywhere_jni.so +0 -0
- package/android/src/main/jniLibs/x86_64/libc++_shared.so +0 -0
- package/android/src/main/jniLibs/x86_64/libomp.so +0 -0
- package/android/src/main/jniLibs/x86_64/librac_commons.so +0 -0
- package/android/src/main/jniLibs/x86_64/librunanywhere_jni.so +0 -0
- package/cpp/HybridRunAnywhereCore.cpp +259 -160
- package/cpp/HybridRunAnywhereCore.hpp +11 -0
- package/cpp/bridges/InitBridge.cpp +234 -3
- package/cpp/bridges/PlatformDownloadBridge.h +44 -0
- package/cpp/bridges/ToolCallingBridge.cpp +188 -0
- package/cpp/bridges/ToolCallingBridge.hpp +98 -0
- package/cpp/third_party/nlohmann/json.hpp +24765 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/RACommons.h +18 -4
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_core.h +11 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion.h +22 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_component.h +263 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_model_registry.h +358 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_platform.h +305 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_service.h +187 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_tokenizer.h +167 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_types.h +454 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_endpoints.h +3 -17
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_image_utils.h +215 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_lifecycle.h +3 -1
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_assignment.h +4 -20
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_registry.h +15 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_types.h +3 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_tool_calling.h +373 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_types.h +8 -6
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vad_energy.h +1 -1
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm.h +16 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_component.h +168 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_llamacpp.h +216 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_service.h +206 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_types.h +417 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/RACommons +0 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/RACommons.h +18 -4
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_core.h +11 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion.h +22 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_component.h +263 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_model_registry.h +358 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_platform.h +305 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_service.h +187 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_tokenizer.h +167 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_types.h +454 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_endpoints.h +3 -17
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_image_utils.h +215 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_lifecycle.h +3 -1
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_assignment.h +4 -20
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_registry.h +15 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_types.h +3 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_tool_calling.h +373 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_types.h +8 -6
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vad_energy.h +1 -1
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm.h +16 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_component.h +168 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_llamacpp.h +216 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_service.h +206 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_types.h +417 -0
- package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/RACommons +0 -0
- package/ios/PlatformAdapterBridge.h +24 -1
- package/ios/PlatformAdapterBridge.m +243 -0
- package/nitrogen/generated/shared/c++/HybridRunAnywhereCoreSpec.cpp +4 -0
- package/nitrogen/generated/shared/c++/HybridRunAnywhereCoreSpec.hpp +4 -0
- package/package.json +8 -4
- package/src/Foundation/Security/SecureStorageService.ts +12 -6
- package/src/Public/Extensions/RunAnywhere+Models.ts +5 -3
- package/src/Public/Extensions/RunAnywhere+STT.ts +7 -2
- package/src/Public/Extensions/RunAnywhere+ToolCalling.ts +472 -0
- package/src/Public/Extensions/index.ts +16 -0
- package/src/Public/RunAnywhere.ts +18 -0
- package/src/index.ts +0 -1
- package/src/services/Network/index.ts +0 -1
- package/src/services/index.ts +0 -1
- package/src/specs/RunAnywhereCore.nitro.ts +72 -0
- package/src/types/ToolCallingTypes.ts +198 -0
- package/src/types/index.ts +13 -0
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
#include "bridges/HTTPBridge.hpp"
|
|
36
36
|
#include "bridges/DownloadBridge.hpp"
|
|
37
37
|
#include "bridges/TelemetryBridge.hpp"
|
|
38
|
+
#include "bridges/ToolCallingBridge.hpp"
|
|
38
39
|
|
|
39
40
|
// RACommons C API headers for capability methods
|
|
40
41
|
// These are backend-agnostic - they work with any registered backend
|
|
@@ -198,6 +199,7 @@ bool extractBoolValue(const std::string& json, const std::string& key, bool defa
|
|
|
198
199
|
rac_inference_framework_t frameworkFromString(const std::string& framework) {
|
|
199
200
|
if (framework == "LlamaCpp" || framework == "llamacpp") return RAC_FRAMEWORK_LLAMACPP;
|
|
200
201
|
if (framework == "ONNX" || framework == "onnx") return RAC_FRAMEWORK_ONNX;
|
|
202
|
+
if (framework == "CoreML" || framework == "coreml") return RAC_FRAMEWORK_COREML;
|
|
201
203
|
if (framework == "FoundationModels") return RAC_FRAMEWORK_FOUNDATION_MODELS;
|
|
202
204
|
if (framework == "SystemTTS") return RAC_FRAMEWORK_SYSTEM_TTS;
|
|
203
205
|
return RAC_FRAMEWORK_UNKNOWN;
|
|
@@ -810,6 +812,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getAvailableModels(
|
|
|
810
812
|
case RAC_MODEL_CATEGORY_SPEECH_RECOGNITION: categoryStr = "speech-recognition"; break;
|
|
811
813
|
case RAC_MODEL_CATEGORY_SPEECH_SYNTHESIS: categoryStr = "speech-synthesis"; break;
|
|
812
814
|
case RAC_MODEL_CATEGORY_VISION: categoryStr = "vision"; break;
|
|
815
|
+
case RAC_MODEL_CATEGORY_IMAGE_GENERATION: categoryStr = "image-generation"; break;
|
|
813
816
|
case RAC_MODEL_CATEGORY_AUDIO: categoryStr = "audio"; break;
|
|
814
817
|
case RAC_MODEL_CATEGORY_MULTIMODAL: categoryStr = "multimodal"; break;
|
|
815
818
|
default: categoryStr = "unknown"; break;
|
|
@@ -826,6 +829,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getAvailableModels(
|
|
|
826
829
|
switch (m.framework) {
|
|
827
830
|
case RAC_FRAMEWORK_LLAMACPP: frameworkStr = "LlamaCpp"; break;
|
|
828
831
|
case RAC_FRAMEWORK_ONNX: frameworkStr = "ONNX"; break;
|
|
832
|
+
case RAC_FRAMEWORK_COREML: frameworkStr = "CoreML"; break;
|
|
829
833
|
case RAC_FRAMEWORK_FOUNDATION_MODELS: frameworkStr = "FoundationModels"; break;
|
|
830
834
|
case RAC_FRAMEWORK_SYSTEM_TTS: frameworkStr = "SystemTTS"; break;
|
|
831
835
|
default: frameworkStr = "unknown"; break;
|
|
@@ -888,6 +892,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getModelInfo(
|
|
|
888
892
|
switch (m.framework) {
|
|
889
893
|
case RAC_FRAMEWORK_LLAMACPP: frameworkStr = "LlamaCpp"; break;
|
|
890
894
|
case RAC_FRAMEWORK_ONNX: frameworkStr = "ONNX"; break;
|
|
895
|
+
case RAC_FRAMEWORK_COREML: frameworkStr = "CoreML"; break;
|
|
891
896
|
case RAC_FRAMEWORK_FOUNDATION_MODELS: frameworkStr = "FoundationModels"; break;
|
|
892
897
|
case RAC_FRAMEWORK_SYSTEM_TTS: frameworkStr = "SystemTTS"; break;
|
|
893
898
|
default: frameworkStr = "unknown"; break;
|
|
@@ -1653,21 +1658,38 @@ std::shared_ptr<Promise<bool>> HybridRunAnywhereCore::loadSTTModel(
|
|
|
1653
1658
|
const std::string& modelType,
|
|
1654
1659
|
const std::optional<std::string>& configJson) {
|
|
1655
1660
|
return Promise<bool>::async([this, modelPath, modelType]() -> bool {
|
|
1656
|
-
|
|
1661
|
+
try {
|
|
1662
|
+
LOGI("Loading STT model: %s", modelPath.c_str());
|
|
1657
1663
|
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
}
|
|
1664
|
+
if (modelPath.empty()) {
|
|
1665
|
+
setLastError("STT model path is empty. Download the model first.");
|
|
1666
|
+
return false;
|
|
1667
|
+
}
|
|
1663
1668
|
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1669
|
+
rac_handle_t handle = getGlobalSTTHandle();
|
|
1670
|
+
if (!handle) {
|
|
1671
|
+
setLastError("Failed to create STT component. Is an STT backend registered?");
|
|
1672
|
+
return false;
|
|
1673
|
+
}
|
|
1668
1674
|
|
|
1669
|
-
|
|
1670
|
-
|
|
1675
|
+
rac_result_t result = rac_stt_component_load_model(
|
|
1676
|
+
handle, modelPath.c_str(), modelPath.c_str(), modelType.c_str());
|
|
1677
|
+
if (result != RAC_SUCCESS) {
|
|
1678
|
+
setLastError("Failed to load STT model: " + std::to_string(result));
|
|
1679
|
+
return false;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
LOGI("STT model loaded successfully");
|
|
1683
|
+
return true;
|
|
1684
|
+
} catch (const std::exception& e) {
|
|
1685
|
+
std::string msg = e.what();
|
|
1686
|
+
LOGI("loadSTTModel exception: %s", msg.c_str());
|
|
1687
|
+
setLastError(msg);
|
|
1688
|
+
return false;
|
|
1689
|
+
} catch (...) {
|
|
1690
|
+
setLastError("STT model load failed (unknown error)");
|
|
1691
|
+
return false;
|
|
1692
|
+
}
|
|
1671
1693
|
});
|
|
1672
1694
|
}
|
|
1673
1695
|
|
|
@@ -1704,57 +1726,71 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::transcribe(
|
|
|
1704
1726
|
double sampleRate,
|
|
1705
1727
|
const std::optional<std::string>& language) {
|
|
1706
1728
|
return Promise<std::string>::async([this, audioBase64, sampleRate, language]() -> std::string {
|
|
1707
|
-
|
|
1729
|
+
try {
|
|
1730
|
+
LOGI("Transcribing audio (base64)...");
|
|
1708
1731
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1732
|
+
rac_handle_t handle = getGlobalSTTHandle();
|
|
1733
|
+
if (!handle) {
|
|
1734
|
+
return "{\"error\":\"STT component not available. Is an STT backend registered?\"}";
|
|
1735
|
+
}
|
|
1713
1736
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1737
|
+
if (rac_stt_component_is_loaded(handle) != RAC_TRUE) {
|
|
1738
|
+
return "{\"error\":\"No STT model loaded. Call loadSTTModel first.\"}";
|
|
1739
|
+
}
|
|
1717
1740
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1741
|
+
// Decode base64 audio data
|
|
1742
|
+
std::vector<uint8_t> audioData = base64Decode(audioBase64);
|
|
1743
|
+
if (audioData.empty()) {
|
|
1744
|
+
return "{\"error\":\"Failed to decode base64 audio data\"}";
|
|
1745
|
+
}
|
|
1723
1746
|
|
|
1724
|
-
|
|
1747
|
+
// Minimum ~0.05s at 16kHz 16-bit to avoid backend crash on tiny input
|
|
1748
|
+
if (audioData.size() < 1600) {
|
|
1749
|
+
return "{\"text\":\"\",\"confidence\":0.0}";
|
|
1750
|
+
}
|
|
1725
1751
|
|
|
1726
|
-
|
|
1727
|
-
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1728
|
-
options.sample_rate = static_cast<int32_t>(sampleRate > 0 ? sampleRate : 16000);
|
|
1729
|
-
options.audio_format = RAC_AUDIO_FORMAT_PCM;
|
|
1730
|
-
if (language.has_value() && !language->empty()) {
|
|
1731
|
-
options.language = language->c_str();
|
|
1732
|
-
}
|
|
1752
|
+
LOGI("Decoded %zu bytes of audio data", audioData.size());
|
|
1733
1753
|
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
&result
|
|
1742
|
-
);
|
|
1754
|
+
// Set up transcription options
|
|
1755
|
+
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1756
|
+
options.sample_rate = static_cast<int32_t>(sampleRate > 0 ? sampleRate : 16000);
|
|
1757
|
+
options.audio_format = RAC_AUDIO_FORMAT_PCM;
|
|
1758
|
+
if (language.has_value() && !language->empty()) {
|
|
1759
|
+
options.language = language->c_str();
|
|
1760
|
+
}
|
|
1743
1761
|
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1762
|
+
// Transcribe
|
|
1763
|
+
rac_stt_result_t result = {};
|
|
1764
|
+
rac_result_t status = rac_stt_component_transcribe(
|
|
1765
|
+
handle,
|
|
1766
|
+
audioData.data(),
|
|
1767
|
+
audioData.size(),
|
|
1768
|
+
&options,
|
|
1769
|
+
&result
|
|
1770
|
+
);
|
|
1771
|
+
|
|
1772
|
+
if (status != RAC_SUCCESS) {
|
|
1773
|
+
rac_stt_result_free(&result);
|
|
1774
|
+
return "{\"error\":\"Transcription failed with error code: " + std::to_string(status) + "\"}";
|
|
1775
|
+
}
|
|
1747
1776
|
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1777
|
+
std::string transcribedText;
|
|
1778
|
+
if (result.text) {
|
|
1779
|
+
transcribedText = std::string(result.text);
|
|
1780
|
+
}
|
|
1781
|
+
float confidence = result.confidence;
|
|
1752
1782
|
|
|
1753
|
-
|
|
1754
|
-
rac_stt_result_free(&result);
|
|
1783
|
+
rac_stt_result_free(&result);
|
|
1755
1784
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1785
|
+
LOGI("Transcription result: %s", transcribedText.c_str());
|
|
1786
|
+
return "{\"text\":" + jsonString(transcribedText) + ",\"confidence\":" + std::to_string(confidence) + "}";
|
|
1787
|
+
} catch (const std::exception& e) {
|
|
1788
|
+
std::string msg = e.what();
|
|
1789
|
+
LOGI("Transcribe exception: %s", msg.c_str());
|
|
1790
|
+
return "{\"error\":" + jsonString(msg) + "}";
|
|
1791
|
+
} catch (...) {
|
|
1792
|
+
return "{\"error\":\"Transcription failed (unknown error)\"}";
|
|
1793
|
+
}
|
|
1758
1794
|
});
|
|
1759
1795
|
}
|
|
1760
1796
|
|
|
@@ -1762,137 +1798,133 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::transcribeFile(
|
|
|
1762
1798
|
const std::string& filePath,
|
|
1763
1799
|
const std::optional<std::string>& language) {
|
|
1764
1800
|
return Promise<std::string>::async([this, filePath, language]() -> std::string {
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
rac_handle_t handle = getGlobalSTTHandle();
|
|
1768
|
-
if (!handle) {
|
|
1769
|
-
throw std::runtime_error("STT component not available. Is an STT backend registered?");
|
|
1770
|
-
}
|
|
1801
|
+
try {
|
|
1802
|
+
LOGI("Transcribing file: %s", filePath.c_str());
|
|
1771
1803
|
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1804
|
+
rac_handle_t handle = getGlobalSTTHandle();
|
|
1805
|
+
if (!handle) {
|
|
1806
|
+
return "{\"error\":\"STT component not available. Is an STT backend registered?\"}";
|
|
1807
|
+
}
|
|
1775
1808
|
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
throw std::runtime_error("Failed to open audio file: " + filePath);
|
|
1780
|
-
}
|
|
1809
|
+
if (rac_stt_component_is_loaded(handle) != RAC_TRUE) {
|
|
1810
|
+
return "{\"error\":\"No STT model loaded. Call loadSTTModel first.\"}";
|
|
1811
|
+
}
|
|
1781
1812
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1813
|
+
// Open the file
|
|
1814
|
+
FILE* file = fopen(filePath.c_str(), "rb");
|
|
1815
|
+
if (!file) {
|
|
1816
|
+
return "{\"error\":\"Failed to open audio file. Check that the path is valid.\"}";
|
|
1817
|
+
}
|
|
1786
1818
|
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1819
|
+
// Get file size
|
|
1820
|
+
fseek(file, 0, SEEK_END);
|
|
1821
|
+
long fileSize = ftell(file);
|
|
1822
|
+
fseek(file, 0, SEEK_SET);
|
|
1791
1823
|
|
|
1792
|
-
|
|
1824
|
+
if (fileSize <= 0) {
|
|
1825
|
+
fclose(file);
|
|
1826
|
+
return "{\"error\":\"Audio file is empty\"}";
|
|
1827
|
+
}
|
|
1793
1828
|
|
|
1794
|
-
|
|
1795
|
-
std::vector<uint8_t> fileData(fileSize);
|
|
1796
|
-
size_t bytesRead = fread(fileData.data(), 1, fileSize, file);
|
|
1797
|
-
fclose(file);
|
|
1829
|
+
LOGI("File size: %ld bytes", fileSize);
|
|
1798
1830
|
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1831
|
+
// Read the entire file into memory
|
|
1832
|
+
std::vector<uint8_t> fileData(static_cast<size_t>(fileSize));
|
|
1833
|
+
size_t bytesRead = fread(fileData.data(), 1, static_cast<size_t>(fileSize), file);
|
|
1834
|
+
fclose(file);
|
|
1802
1835
|
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1836
|
+
if (bytesRead != static_cast<size_t>(fileSize)) {
|
|
1837
|
+
return "{\"error\":\"Failed to read audio file completely\"}";
|
|
1838
|
+
}
|
|
1806
1839
|
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1840
|
+
// Parse WAV header to extract audio data
|
|
1841
|
+
const uint8_t* data = fileData.data();
|
|
1842
|
+
size_t dataSize = fileData.size();
|
|
1843
|
+
int32_t sampleRate = 16000;
|
|
1810
1844
|
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1845
|
+
if (dataSize < 44) {
|
|
1846
|
+
return "{\"error\":\"File too small to be a valid WAV file\"}";
|
|
1847
|
+
}
|
|
1848
|
+
if (data[0] != 'R' || data[1] != 'I' || data[2] != 'F' || data[3] != 'F') {
|
|
1849
|
+
return "{\"error\":\"Invalid WAV file: missing RIFF header\"}";
|
|
1850
|
+
}
|
|
1851
|
+
if (data[8] != 'W' || data[9] != 'A' || data[10] != 'V' || data[11] != 'E') {
|
|
1852
|
+
return "{\"error\":\"Invalid WAV file: missing WAVE format\"}";
|
|
1853
|
+
}
|
|
1815
1854
|
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
}
|
|
1855
|
+
size_t pos = 12;
|
|
1856
|
+
size_t audioDataOffset = 0;
|
|
1857
|
+
size_t audioDataSize = 0;
|
|
1820
1858
|
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1859
|
+
while (pos + 8 < dataSize) {
|
|
1860
|
+
char chunkId[5] = {0};
|
|
1861
|
+
memcpy(chunkId, &data[pos], 4);
|
|
1862
|
+
uint32_t chunkSize = *reinterpret_cast<const uint32_t*>(&data[pos + 4]);
|
|
1825
1863
|
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1864
|
+
if (strcmp(chunkId, "fmt ") == 0) {
|
|
1865
|
+
if (pos + 8 + chunkSize <= dataSize && chunkSize >= 16) {
|
|
1866
|
+
sampleRate = *reinterpret_cast<const int32_t*>(&data[pos + 12]);
|
|
1867
|
+
if (sampleRate <= 0 || sampleRate > 48000) sampleRate = 16000;
|
|
1868
|
+
LOGI("WAV sample rate: %d Hz", sampleRate);
|
|
1869
|
+
}
|
|
1870
|
+
} else if (strcmp(chunkId, "data") == 0) {
|
|
1871
|
+
audioDataOffset = pos + 8;
|
|
1872
|
+
audioDataSize = chunkSize;
|
|
1873
|
+
LOGI("Found audio data: offset=%zu, size=%zu", audioDataOffset, audioDataSize);
|
|
1874
|
+
break;
|
|
1875
|
+
}
|
|
1830
1876
|
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
uint32_t chunkSize = *reinterpret_cast<const uint32_t*>(&data[pos + 4]);
|
|
1877
|
+
pos += 8 + chunkSize;
|
|
1878
|
+
if (chunkSize % 2 != 0) pos++;
|
|
1879
|
+
}
|
|
1835
1880
|
|
|
1836
|
-
if (
|
|
1837
|
-
|
|
1838
|
-
if (pos + 8 + chunkSize <= dataSize && chunkSize >= 16) {
|
|
1839
|
-
// Bytes 12-13: Audio format (1 = PCM)
|
|
1840
|
-
// Bytes 14-15: Number of channels
|
|
1841
|
-
// Bytes 16-19: Sample rate
|
|
1842
|
-
sampleRate = *reinterpret_cast<const int32_t*>(&data[pos + 12]);
|
|
1843
|
-
LOGI("WAV sample rate: %d Hz", sampleRate);
|
|
1844
|
-
}
|
|
1845
|
-
} else if (strcmp(chunkId, "data") == 0) {
|
|
1846
|
-
// Found data chunk
|
|
1847
|
-
audioDataOffset = pos + 8;
|
|
1848
|
-
audioDataSize = chunkSize;
|
|
1849
|
-
LOGI("Found audio data: offset=%zu, size=%zu", audioDataOffset, audioDataSize);
|
|
1850
|
-
break;
|
|
1881
|
+
if (audioDataSize == 0 || audioDataOffset + audioDataSize > dataSize) {
|
|
1882
|
+
return "{\"error\":\"Could not find valid audio data in WAV file\"}";
|
|
1851
1883
|
}
|
|
1852
1884
|
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1885
|
+
// Minimum ~0.1s at 16kHz 16-bit; avoid empty or tiny buffers
|
|
1886
|
+
if (audioDataSize < 3200) {
|
|
1887
|
+
return "{\"error\":\"Recording too short to transcribe\"}";
|
|
1888
|
+
}
|
|
1857
1889
|
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1890
|
+
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1891
|
+
options.sample_rate = sampleRate;
|
|
1892
|
+
options.audio_format = RAC_AUDIO_FORMAT_PCM;
|
|
1893
|
+
if (language.has_value() && !language->empty()) {
|
|
1894
|
+
options.language = language->c_str();
|
|
1895
|
+
}
|
|
1861
1896
|
|
|
1862
|
-
|
|
1863
|
-
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1864
|
-
options.sample_rate = sampleRate;
|
|
1865
|
-
options.audio_format = RAC_AUDIO_FORMAT_WAV; // Tell the backend it's WAV format
|
|
1866
|
-
if (language.has_value() && !language->empty()) {
|
|
1867
|
-
options.language = language->c_str();
|
|
1868
|
-
}
|
|
1897
|
+
LOGI("Transcribing %zu bytes of audio at %d Hz", audioDataSize, sampleRate);
|
|
1869
1898
|
|
|
1870
|
-
|
|
1899
|
+
rac_stt_result_t result = {};
|
|
1900
|
+
rac_result_t status = rac_stt_component_transcribe(
|
|
1901
|
+
handle,
|
|
1902
|
+
&data[audioDataOffset],
|
|
1903
|
+
audioDataSize,
|
|
1904
|
+
&options,
|
|
1905
|
+
&result
|
|
1906
|
+
);
|
|
1871
1907
|
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
&data[audioDataOffset],
|
|
1877
|
-
audioDataSize,
|
|
1878
|
-
&options,
|
|
1879
|
-
&result
|
|
1880
|
-
);
|
|
1908
|
+
if (status != RAC_SUCCESS) {
|
|
1909
|
+
rac_stt_result_free(&result);
|
|
1910
|
+
return "{\"error\":\"Transcription failed with error code: " + std::to_string(status) + "\"}";
|
|
1911
|
+
}
|
|
1881
1912
|
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1913
|
+
std::string transcribedText;
|
|
1914
|
+
if (result.text) {
|
|
1915
|
+
transcribedText = std::string(result.text);
|
|
1916
|
+
}
|
|
1885
1917
|
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
transcribedText
|
|
1918
|
+
rac_stt_result_free(&result);
|
|
1919
|
+
LOGI("Transcription result: %s", transcribedText.c_str());
|
|
1920
|
+
return transcribedText;
|
|
1921
|
+
} catch (const std::exception& e) {
|
|
1922
|
+
std::string msg = e.what();
|
|
1923
|
+
LOGI("TranscribeFile exception: %s", msg.c_str());
|
|
1924
|
+
return "{\"error\":\"" + msg + "\"}";
|
|
1925
|
+
} catch (...) {
|
|
1926
|
+
return "{\"error\":\"Transcription failed (unknown error)\"}";
|
|
1889
1927
|
}
|
|
1890
|
-
|
|
1891
|
-
// Free the result
|
|
1892
|
-
rac_stt_result_free(&result);
|
|
1893
|
-
|
|
1894
|
-
LOGI("Transcription result: %s", transcribedText.c_str());
|
|
1895
|
-
return transcribedText;
|
|
1896
1928
|
});
|
|
1897
1929
|
}
|
|
1898
1930
|
|
|
@@ -2569,4 +2601,71 @@ std::shared_ptr<Promise<bool>> HybridRunAnywhereCore::isTelemetryInitialized() {
|
|
|
2569
2601
|
});
|
|
2570
2602
|
}
|
|
2571
2603
|
|
|
2604
|
+
// ============================================================================
|
|
2605
|
+
// Tool Calling
|
|
2606
|
+
//
|
|
2607
|
+
// ARCHITECTURE:
|
|
2608
|
+
// - C++ (ToolCallingBridge): Parses <tool_call> tags from LLM output.
|
|
2609
|
+
// This is the SINGLE SOURCE OF TRUTH for parsing, ensuring consistency.
|
|
2610
|
+
//
|
|
2611
|
+
// - TypeScript (RunAnywhere+ToolCalling.ts): Handles tool registry, executor
|
|
2612
|
+
// storage, prompt formatting, and orchestration. Executors MUST stay in
|
|
2613
|
+
// TypeScript because they need JavaScript APIs (fetch, device APIs, etc.).
|
|
2614
|
+
//
|
|
2615
|
+
// Only parseToolCallFromOutput is implemented in C++. All other tool calling
|
|
2616
|
+
// functionality (registration, execution, prompt formatting) is in TypeScript.
|
|
2617
|
+
// ============================================================================
|
|
2618
|
+
|
|
2619
|
+
std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::parseToolCallFromOutput(const std::string& llmOutput) {
|
|
2620
|
+
return Promise<std::string>::async([llmOutput]() -> std::string {
|
|
2621
|
+
LOGD("parseToolCallFromOutput: input length=%zu", llmOutput.length());
|
|
2622
|
+
|
|
2623
|
+
// Use ToolCallingBridge for parsing - single source of truth
|
|
2624
|
+
// This ensures consistent <tool_call> tag parsing across all platforms
|
|
2625
|
+
return ::runanywhere::bridges::ToolCallingBridge::shared().parseToolCall(llmOutput);
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::formatToolsForPrompt(
|
|
2630
|
+
const std::string& toolsJson,
|
|
2631
|
+
const std::string& format
|
|
2632
|
+
) {
|
|
2633
|
+
return Promise<std::string>::async([toolsJson, format]() -> std::string {
|
|
2634
|
+
LOGD("formatToolsForPrompt: tools length=%zu, format=%s", toolsJson.length(), format.c_str());
|
|
2635
|
+
|
|
2636
|
+
// Use C++ single source of truth for prompt formatting
|
|
2637
|
+
// This eliminates duplicate TypeScript implementation
|
|
2638
|
+
return ::runanywhere::bridges::ToolCallingBridge::shared().formatToolsPrompt(toolsJson, format);
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::buildInitialPrompt(
|
|
2643
|
+
const std::string& userPrompt,
|
|
2644
|
+
const std::string& toolsJson,
|
|
2645
|
+
const std::string& optionsJson
|
|
2646
|
+
) {
|
|
2647
|
+
return Promise<std::string>::async([userPrompt, toolsJson, optionsJson]() -> std::string {
|
|
2648
|
+
LOGD("buildInitialPrompt: prompt length=%zu, tools length=%zu", userPrompt.length(), toolsJson.length());
|
|
2649
|
+
|
|
2650
|
+
// Use C++ single source of truth for initial prompt building
|
|
2651
|
+
return ::runanywhere::bridges::ToolCallingBridge::shared().buildInitialPrompt(userPrompt, toolsJson, optionsJson);
|
|
2652
|
+
});
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::buildFollowupPrompt(
|
|
2656
|
+
const std::string& originalPrompt,
|
|
2657
|
+
const std::string& toolsPrompt,
|
|
2658
|
+
const std::string& toolName,
|
|
2659
|
+
const std::string& resultJson,
|
|
2660
|
+
bool keepToolsAvailable
|
|
2661
|
+
) {
|
|
2662
|
+
return Promise<std::string>::async([originalPrompt, toolsPrompt, toolName, resultJson, keepToolsAvailable]() -> std::string {
|
|
2663
|
+
LOGD("buildFollowupPrompt: tool=%s, keepTools=%d", toolName.c_str(), keepToolsAvailable);
|
|
2664
|
+
|
|
2665
|
+
// Use C++ single source of truth for follow-up prompt building
|
|
2666
|
+
return ::runanywhere::bridges::ToolCallingBridge::shared().buildFollowupPrompt(
|
|
2667
|
+
originalPrompt, toolsPrompt, toolName, resultJson, keepToolsAvailable);
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2572
2671
|
} // namespace margelo::nitro::runanywhere
|
|
@@ -257,6 +257,17 @@ public:
|
|
|
257
257
|
std::shared_ptr<Promise<std::string>> voiceAgentSynthesizeSpeech(const std::string& text) override;
|
|
258
258
|
std::shared_ptr<Promise<void>> cleanupVoiceAgent() override;
|
|
259
259
|
|
|
260
|
+
// ============================================================================
|
|
261
|
+
// Tool Calling - Delegates to ToolCallingBridge
|
|
262
|
+
// Single source of truth for parsing, formatting, and prompt building
|
|
263
|
+
// Tool registry and execution are in TypeScript (RunAnywhere+ToolCalling.ts)
|
|
264
|
+
// ============================================================================
|
|
265
|
+
|
|
266
|
+
std::shared_ptr<Promise<std::string>> parseToolCallFromOutput(const std::string& llmOutput) override;
|
|
267
|
+
std::shared_ptr<Promise<std::string>> formatToolsForPrompt(const std::string& toolsJson, const std::string& format) override;
|
|
268
|
+
std::shared_ptr<Promise<std::string>> buildInitialPrompt(const std::string& userPrompt, const std::string& toolsJson, const std::string& optionsJson) override;
|
|
269
|
+
std::shared_ptr<Promise<std::string>> buildFollowupPrompt(const std::string& originalPrompt, const std::string& toolsPrompt, const std::string& toolName, const std::string& resultJson, bool keepToolsAvailable) override;
|
|
270
|
+
|
|
260
271
|
private:
|
|
261
272
|
// Thread safety
|
|
262
273
|
std::mutex initMutex_;
|