@runanywhere/core 0.17.8 → 0.18.1
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 +263 -163
- 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;
|
|
@@ -421,12 +423,13 @@ std::shared_ptr<Promise<bool>> HybridRunAnywhereCore::initialize(
|
|
|
421
423
|
};
|
|
422
424
|
|
|
423
425
|
callbacks.user_data = nullptr;
|
|
424
|
-
//
|
|
425
|
-
|
|
426
|
+
// Only auto-fetch in staging/production, not development
|
|
427
|
+
bool shouldAutoFetch = (env != SDKEnvironment::Development);
|
|
428
|
+
callbacks.auto_fetch = shouldAutoFetch ? RAC_TRUE : RAC_FALSE;
|
|
426
429
|
|
|
427
430
|
result = rac_model_assignment_set_callbacks(&callbacks);
|
|
428
431
|
if (result == RAC_SUCCESS) {
|
|
429
|
-
LOGI("Model assignment callbacks registered");
|
|
432
|
+
LOGI("Model assignment callbacks registered (autoFetch: %s)", shouldAutoFetch ? "true" : "false");
|
|
430
433
|
} else {
|
|
431
434
|
LOGE("Failed to register model assignment callbacks: %d", result);
|
|
432
435
|
// Continue - not fatal, models can be fetched later
|
|
@@ -809,6 +812,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getAvailableModels(
|
|
|
809
812
|
case RAC_MODEL_CATEGORY_SPEECH_RECOGNITION: categoryStr = "speech-recognition"; break;
|
|
810
813
|
case RAC_MODEL_CATEGORY_SPEECH_SYNTHESIS: categoryStr = "speech-synthesis"; break;
|
|
811
814
|
case RAC_MODEL_CATEGORY_VISION: categoryStr = "vision"; break;
|
|
815
|
+
case RAC_MODEL_CATEGORY_IMAGE_GENERATION: categoryStr = "image-generation"; break;
|
|
812
816
|
case RAC_MODEL_CATEGORY_AUDIO: categoryStr = "audio"; break;
|
|
813
817
|
case RAC_MODEL_CATEGORY_MULTIMODAL: categoryStr = "multimodal"; break;
|
|
814
818
|
default: categoryStr = "unknown"; break;
|
|
@@ -825,6 +829,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getAvailableModels(
|
|
|
825
829
|
switch (m.framework) {
|
|
826
830
|
case RAC_FRAMEWORK_LLAMACPP: frameworkStr = "LlamaCpp"; break;
|
|
827
831
|
case RAC_FRAMEWORK_ONNX: frameworkStr = "ONNX"; break;
|
|
832
|
+
case RAC_FRAMEWORK_COREML: frameworkStr = "CoreML"; break;
|
|
828
833
|
case RAC_FRAMEWORK_FOUNDATION_MODELS: frameworkStr = "FoundationModels"; break;
|
|
829
834
|
case RAC_FRAMEWORK_SYSTEM_TTS: frameworkStr = "SystemTTS"; break;
|
|
830
835
|
default: frameworkStr = "unknown"; break;
|
|
@@ -887,6 +892,7 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::getModelInfo(
|
|
|
887
892
|
switch (m.framework) {
|
|
888
893
|
case RAC_FRAMEWORK_LLAMACPP: frameworkStr = "LlamaCpp"; break;
|
|
889
894
|
case RAC_FRAMEWORK_ONNX: frameworkStr = "ONNX"; break;
|
|
895
|
+
case RAC_FRAMEWORK_COREML: frameworkStr = "CoreML"; break;
|
|
890
896
|
case RAC_FRAMEWORK_FOUNDATION_MODELS: frameworkStr = "FoundationModels"; break;
|
|
891
897
|
case RAC_FRAMEWORK_SYSTEM_TTS: frameworkStr = "SystemTTS"; break;
|
|
892
898
|
default: frameworkStr = "unknown"; break;
|
|
@@ -1652,21 +1658,38 @@ std::shared_ptr<Promise<bool>> HybridRunAnywhereCore::loadSTTModel(
|
|
|
1652
1658
|
const std::string& modelType,
|
|
1653
1659
|
const std::optional<std::string>& configJson) {
|
|
1654
1660
|
return Promise<bool>::async([this, modelPath, modelType]() -> bool {
|
|
1655
|
-
|
|
1661
|
+
try {
|
|
1662
|
+
LOGI("Loading STT model: %s", modelPath.c_str());
|
|
1656
1663
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
}
|
|
1664
|
+
if (modelPath.empty()) {
|
|
1665
|
+
setLastError("STT model path is empty. Download the model first.");
|
|
1666
|
+
return false;
|
|
1667
|
+
}
|
|
1662
1668
|
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
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
|
+
}
|
|
1667
1674
|
|
|
1668
|
-
|
|
1669
|
-
|
|
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
|
+
}
|
|
1670
1693
|
});
|
|
1671
1694
|
}
|
|
1672
1695
|
|
|
@@ -1703,57 +1726,71 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::transcribe(
|
|
|
1703
1726
|
double sampleRate,
|
|
1704
1727
|
const std::optional<std::string>& language) {
|
|
1705
1728
|
return Promise<std::string>::async([this, audioBase64, sampleRate, language]() -> std::string {
|
|
1706
|
-
|
|
1729
|
+
try {
|
|
1730
|
+
LOGI("Transcribing audio (base64)...");
|
|
1707
1731
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1732
|
+
rac_handle_t handle = getGlobalSTTHandle();
|
|
1733
|
+
if (!handle) {
|
|
1734
|
+
return "{\"error\":\"STT component not available. Is an STT backend registered?\"}";
|
|
1735
|
+
}
|
|
1712
1736
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1737
|
+
if (rac_stt_component_is_loaded(handle) != RAC_TRUE) {
|
|
1738
|
+
return "{\"error\":\"No STT model loaded. Call loadSTTModel first.\"}";
|
|
1739
|
+
}
|
|
1716
1740
|
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
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
|
+
}
|
|
1722
1746
|
|
|
1723
|
-
|
|
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
|
+
}
|
|
1724
1751
|
|
|
1725
|
-
|
|
1726
|
-
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1727
|
-
options.sample_rate = static_cast<int32_t>(sampleRate > 0 ? sampleRate : 16000);
|
|
1728
|
-
options.audio_format = RAC_AUDIO_FORMAT_PCM;
|
|
1729
|
-
if (language.has_value() && !language->empty()) {
|
|
1730
|
-
options.language = language->c_str();
|
|
1731
|
-
}
|
|
1752
|
+
LOGI("Decoded %zu bytes of audio data", audioData.size());
|
|
1732
1753
|
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
&result
|
|
1741
|
-
);
|
|
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
|
+
}
|
|
1742
1761
|
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
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
|
+
}
|
|
1746
1776
|
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1777
|
+
std::string transcribedText;
|
|
1778
|
+
if (result.text) {
|
|
1779
|
+
transcribedText = std::string(result.text);
|
|
1780
|
+
}
|
|
1781
|
+
float confidence = result.confidence;
|
|
1751
1782
|
|
|
1752
|
-
|
|
1753
|
-
rac_stt_result_free(&result);
|
|
1783
|
+
rac_stt_result_free(&result);
|
|
1754
1784
|
|
|
1755
|
-
|
|
1756
|
-
|
|
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
|
+
}
|
|
1757
1794
|
});
|
|
1758
1795
|
}
|
|
1759
1796
|
|
|
@@ -1761,137 +1798,133 @@ std::shared_ptr<Promise<std::string>> HybridRunAnywhereCore::transcribeFile(
|
|
|
1761
1798
|
const std::string& filePath,
|
|
1762
1799
|
const std::optional<std::string>& language) {
|
|
1763
1800
|
return Promise<std::string>::async([this, filePath, language]() -> std::string {
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
rac_handle_t handle = getGlobalSTTHandle();
|
|
1767
|
-
if (!handle) {
|
|
1768
|
-
throw std::runtime_error("STT component not available. Is an STT backend registered?");
|
|
1769
|
-
}
|
|
1801
|
+
try {
|
|
1802
|
+
LOGI("Transcribing file: %s", filePath.c_str());
|
|
1770
1803
|
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1804
|
+
rac_handle_t handle = getGlobalSTTHandle();
|
|
1805
|
+
if (!handle) {
|
|
1806
|
+
return "{\"error\":\"STT component not available. Is an STT backend registered?\"}";
|
|
1807
|
+
}
|
|
1774
1808
|
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
throw std::runtime_error("Failed to open audio file: " + filePath);
|
|
1779
|
-
}
|
|
1809
|
+
if (rac_stt_component_is_loaded(handle) != RAC_TRUE) {
|
|
1810
|
+
return "{\"error\":\"No STT model loaded. Call loadSTTModel first.\"}";
|
|
1811
|
+
}
|
|
1780
1812
|
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
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
|
+
}
|
|
1785
1818
|
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1819
|
+
// Get file size
|
|
1820
|
+
fseek(file, 0, SEEK_END);
|
|
1821
|
+
long fileSize = ftell(file);
|
|
1822
|
+
fseek(file, 0, SEEK_SET);
|
|
1790
1823
|
|
|
1791
|
-
|
|
1824
|
+
if (fileSize <= 0) {
|
|
1825
|
+
fclose(file);
|
|
1826
|
+
return "{\"error\":\"Audio file is empty\"}";
|
|
1827
|
+
}
|
|
1792
1828
|
|
|
1793
|
-
|
|
1794
|
-
std::vector<uint8_t> fileData(fileSize);
|
|
1795
|
-
size_t bytesRead = fread(fileData.data(), 1, fileSize, file);
|
|
1796
|
-
fclose(file);
|
|
1829
|
+
LOGI("File size: %ld bytes", fileSize);
|
|
1797
1830
|
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
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);
|
|
1801
1835
|
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1836
|
+
if (bytesRead != static_cast<size_t>(fileSize)) {
|
|
1837
|
+
return "{\"error\":\"Failed to read audio file completely\"}";
|
|
1838
|
+
}
|
|
1805
1839
|
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
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;
|
|
1809
1844
|
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
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
|
+
}
|
|
1814
1854
|
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1855
|
+
size_t pos = 12;
|
|
1856
|
+
size_t audioDataOffset = 0;
|
|
1857
|
+
size_t audioDataSize = 0;
|
|
1819
1858
|
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
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]);
|
|
1824
1863
|
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
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
|
+
}
|
|
1829
1876
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
uint32_t chunkSize = *reinterpret_cast<const uint32_t*>(&data[pos + 4]);
|
|
1877
|
+
pos += 8 + chunkSize;
|
|
1878
|
+
if (chunkSize % 2 != 0) pos++;
|
|
1879
|
+
}
|
|
1834
1880
|
|
|
1835
|
-
if (
|
|
1836
|
-
|
|
1837
|
-
if (pos + 8 + chunkSize <= dataSize && chunkSize >= 16) {
|
|
1838
|
-
// Bytes 12-13: Audio format (1 = PCM)
|
|
1839
|
-
// Bytes 14-15: Number of channels
|
|
1840
|
-
// Bytes 16-19: Sample rate
|
|
1841
|
-
sampleRate = *reinterpret_cast<const int32_t*>(&data[pos + 12]);
|
|
1842
|
-
LOGI("WAV sample rate: %d Hz", sampleRate);
|
|
1843
|
-
}
|
|
1844
|
-
} else if (strcmp(chunkId, "data") == 0) {
|
|
1845
|
-
// Found data chunk
|
|
1846
|
-
audioDataOffset = pos + 8;
|
|
1847
|
-
audioDataSize = chunkSize;
|
|
1848
|
-
LOGI("Found audio data: offset=%zu, size=%zu", audioDataOffset, audioDataSize);
|
|
1849
|
-
break;
|
|
1881
|
+
if (audioDataSize == 0 || audioDataOffset + audioDataSize > dataSize) {
|
|
1882
|
+
return "{\"error\":\"Could not find valid audio data in WAV file\"}";
|
|
1850
1883
|
}
|
|
1851
1884
|
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
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
|
+
}
|
|
1856
1889
|
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
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
|
+
}
|
|
1860
1896
|
|
|
1861
|
-
|
|
1862
|
-
rac_stt_options_t options = RAC_STT_OPTIONS_DEFAULT;
|
|
1863
|
-
options.sample_rate = sampleRate;
|
|
1864
|
-
options.audio_format = RAC_AUDIO_FORMAT_WAV; // Tell the backend it's WAV format
|
|
1865
|
-
if (language.has_value() && !language->empty()) {
|
|
1866
|
-
options.language = language->c_str();
|
|
1867
|
-
}
|
|
1897
|
+
LOGI("Transcribing %zu bytes of audio at %d Hz", audioDataSize, sampleRate);
|
|
1868
1898
|
|
|
1869
|
-
|
|
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
|
+
);
|
|
1870
1907
|
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
&data[audioDataOffset],
|
|
1876
|
-
audioDataSize,
|
|
1877
|
-
&options,
|
|
1878
|
-
&result
|
|
1879
|
-
);
|
|
1908
|
+
if (status != RAC_SUCCESS) {
|
|
1909
|
+
rac_stt_result_free(&result);
|
|
1910
|
+
return "{\"error\":\"Transcription failed with error code: " + std::to_string(status) + "\"}";
|
|
1911
|
+
}
|
|
1880
1912
|
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1913
|
+
std::string transcribedText;
|
|
1914
|
+
if (result.text) {
|
|
1915
|
+
transcribedText = std::string(result.text);
|
|
1916
|
+
}
|
|
1884
1917
|
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
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)\"}";
|
|
1888
1927
|
}
|
|
1889
|
-
|
|
1890
|
-
// Free the result
|
|
1891
|
-
rac_stt_result_free(&result);
|
|
1892
|
-
|
|
1893
|
-
LOGI("Transcription result: %s", transcribedText.c_str());
|
|
1894
|
-
return transcribedText;
|
|
1895
1928
|
});
|
|
1896
1929
|
}
|
|
1897
1930
|
|
|
@@ -2568,4 +2601,71 @@ std::shared_ptr<Promise<bool>> HybridRunAnywhereCore::isTelemetryInitialized() {
|
|
|
2568
2601
|
});
|
|
2569
2602
|
}
|
|
2570
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
|
+
|
|
2571
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_;
|