@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.
Files changed (106) hide show
  1. package/README.md +218 -2
  2. package/RunAnywhereCore.podspec +1 -0
  3. package/android/CMakeLists.txt +24 -2
  4. package/android/build.gradle +61 -9
  5. package/android/src/main/cpp/cpp-adapter.cpp +51 -3
  6. package/android/src/main/include/rac/backends/rac_vlm_llamacpp.h +216 -0
  7. package/android/src/main/include/rac/core/capabilities/rac_lifecycle.h +3 -1
  8. package/android/src/main/include/rac/core/rac_core.h +11 -0
  9. package/android/src/main/include/rac/core/rac_types.h +8 -6
  10. package/android/src/main/include/rac/features/diffusion/rac_diffusion.h +22 -0
  11. package/android/src/main/include/rac/features/diffusion/rac_diffusion_component.h +263 -0
  12. package/android/src/main/include/rac/features/diffusion/rac_diffusion_model_registry.h +358 -0
  13. package/android/src/main/include/rac/features/diffusion/rac_diffusion_service.h +187 -0
  14. package/android/src/main/include/rac/features/diffusion/rac_diffusion_tokenizer.h +167 -0
  15. package/android/src/main/include/rac/features/diffusion/rac_diffusion_types.h +454 -0
  16. package/android/src/main/include/rac/features/llm/rac_tool_calling.h +373 -0
  17. package/android/src/main/include/rac/features/platform/rac_diffusion_platform.h +305 -0
  18. package/android/src/main/include/rac/features/vad/rac_vad_energy.h +1 -1
  19. package/android/src/main/include/rac/features/vlm/rac_vlm.h +16 -0
  20. package/android/src/main/include/rac/features/vlm/rac_vlm_component.h +168 -0
  21. package/android/src/main/include/rac/features/vlm/rac_vlm_service.h +206 -0
  22. package/android/src/main/include/rac/features/vlm/rac_vlm_types.h +417 -0
  23. package/android/src/main/include/rac/infrastructure/model_management/rac_model_registry.h +15 -0
  24. package/android/src/main/include/rac/infrastructure/model_management/rac_model_types.h +3 -0
  25. package/android/src/main/include/rac/utils/rac_image_utils.h +215 -0
  26. package/android/src/main/java/com/margelo/nitro/runanywhere/PlatformAdapterBridge.kt +201 -1
  27. package/android/src/main/jniLibs/arm64-v8a/libc++_shared.so +0 -0
  28. package/android/src/main/jniLibs/arm64-v8a/libomp.so +0 -0
  29. package/android/src/main/jniLibs/arm64-v8a/librac_commons.so +0 -0
  30. package/android/src/main/jniLibs/arm64-v8a/librunanywhere_jni.so +0 -0
  31. package/android/src/main/jniLibs/x86_64/libc++_shared.so +0 -0
  32. package/android/src/main/jniLibs/x86_64/libomp.so +0 -0
  33. package/android/src/main/jniLibs/x86_64/librac_commons.so +0 -0
  34. package/android/src/main/jniLibs/x86_64/librunanywhere_jni.so +0 -0
  35. package/cpp/HybridRunAnywhereCore.cpp +259 -160
  36. package/cpp/HybridRunAnywhereCore.hpp +11 -0
  37. package/cpp/bridges/InitBridge.cpp +234 -3
  38. package/cpp/bridges/PlatformDownloadBridge.h +44 -0
  39. package/cpp/bridges/ToolCallingBridge.cpp +188 -0
  40. package/cpp/bridges/ToolCallingBridge.hpp +98 -0
  41. package/cpp/third_party/nlohmann/json.hpp +24765 -0
  42. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/RACommons.h +18 -4
  43. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_core.h +11 -0
  44. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion.h +22 -0
  45. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_component.h +263 -0
  46. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_model_registry.h +358 -0
  47. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_platform.h +305 -0
  48. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_service.h +187 -0
  49. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_tokenizer.h +167 -0
  50. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_diffusion_types.h +454 -0
  51. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_endpoints.h +3 -17
  52. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_image_utils.h +215 -0
  53. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_lifecycle.h +3 -1
  54. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_assignment.h +4 -20
  55. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_registry.h +15 -0
  56. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_model_types.h +3 -0
  57. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_tool_calling.h +373 -0
  58. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_types.h +8 -6
  59. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vad_energy.h +1 -1
  60. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm.h +16 -0
  61. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_component.h +168 -0
  62. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_llamacpp.h +216 -0
  63. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_service.h +206 -0
  64. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers/rac_vlm_types.h +417 -0
  65. package/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/RACommons +0 -0
  66. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/RACommons.h +18 -4
  67. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_core.h +11 -0
  68. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion.h +22 -0
  69. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_component.h +263 -0
  70. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_model_registry.h +358 -0
  71. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_platform.h +305 -0
  72. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_service.h +187 -0
  73. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_tokenizer.h +167 -0
  74. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_diffusion_types.h +454 -0
  75. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_endpoints.h +3 -17
  76. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_image_utils.h +215 -0
  77. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_lifecycle.h +3 -1
  78. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_assignment.h +4 -20
  79. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_registry.h +15 -0
  80. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_model_types.h +3 -0
  81. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_tool_calling.h +373 -0
  82. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_types.h +8 -6
  83. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vad_energy.h +1 -1
  84. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm.h +16 -0
  85. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_component.h +168 -0
  86. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_llamacpp.h +216 -0
  87. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_service.h +206 -0
  88. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers/rac_vlm_types.h +417 -0
  89. package/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/RACommons +0 -0
  90. package/ios/PlatformAdapterBridge.h +24 -1
  91. package/ios/PlatformAdapterBridge.m +243 -0
  92. package/nitrogen/generated/shared/c++/HybridRunAnywhereCoreSpec.cpp +4 -0
  93. package/nitrogen/generated/shared/c++/HybridRunAnywhereCoreSpec.hpp +4 -0
  94. package/package.json +8 -4
  95. package/src/Foundation/Security/SecureStorageService.ts +12 -6
  96. package/src/Public/Extensions/RunAnywhere+Models.ts +5 -3
  97. package/src/Public/Extensions/RunAnywhere+STT.ts +7 -2
  98. package/src/Public/Extensions/RunAnywhere+ToolCalling.ts +472 -0
  99. package/src/Public/Extensions/index.ts +16 -0
  100. package/src/Public/RunAnywhere.ts +18 -0
  101. package/src/index.ts +0 -1
  102. package/src/services/Network/index.ts +0 -1
  103. package/src/services/index.ts +0 -1
  104. package/src/specs/RunAnywhereCore.nitro.ts +72 -0
  105. package/src/types/ToolCallingTypes.ts +198 -0
  106. package/src/types/index.ts +13 -0
package/README.md CHANGED
@@ -9,6 +9,8 @@ Core SDK for RunAnywhere React Native. Foundation package providing the public A
9
9
  `@runanywhere/core` is the foundation package of the RunAnywhere React Native SDK. It provides:
10
10
 
11
11
  - **RunAnywhere API** — Main SDK singleton with all public methods
12
+ - **Tool Calling** — Register tools and let LLMs call them during generation
13
+ - **Structured Output** — Generate type-safe JSON responses with schema validation
12
14
  - **EventBus** — Event subscription system for SDK events
13
15
  - **ModelRegistry** — Model metadata management and discovery
14
16
  - **DownloadService** — Model downloads with progress and resume
@@ -143,6 +145,190 @@ await RunAnywhere.cleanTempFiles();
143
145
 
144
146
  ---
145
147
 
148
+ ### Tool Calling
149
+
150
+ Register tools that LLMs can invoke during generation. Tool calling enables models to request external actions (API calls, device functions, calculations, etc.) and incorporate the results into their responses.
151
+
152
+ #### Register a Tool
153
+
154
+ ```typescript
155
+ import { RunAnywhere } from '@runanywhere/core';
156
+
157
+ RunAnywhere.registerTool(
158
+ {
159
+ name: 'get_weather',
160
+ description: 'Get the current weather for a location',
161
+ parameters: [
162
+ {
163
+ name: 'location',
164
+ type: 'string',
165
+ description: 'City name or coordinates',
166
+ required: true,
167
+ },
168
+ {
169
+ name: 'units',
170
+ type: 'string',
171
+ description: 'Temperature units',
172
+ required: false,
173
+ enum: ['celsius', 'fahrenheit'],
174
+ },
175
+ ],
176
+ },
177
+ async (args) => {
178
+ // Your tool implementation
179
+ const response = await fetch(`https://api.weather.com?q=${args.location}`);
180
+ const data = await response.json();
181
+ return { temperature: data.temp, condition: data.condition };
182
+ }
183
+ );
184
+ ```
185
+
186
+ #### Generate with Tools
187
+
188
+ ```typescript
189
+ const result = await RunAnywhere.generateWithTools(
190
+ 'What is the weather in San Francisco?',
191
+ {
192
+ autoExecute: true, // Automatically execute tool calls
193
+ maxToolCalls: 3, // Max tool invocations per turn
194
+ temperature: 0.7,
195
+ maxTokens: 512,
196
+ format: 'default', // 'default' or 'lfm2' for Liquid AI models
197
+ keepToolsAvailable: false, // Remove tools after first call
198
+ }
199
+ );
200
+
201
+ console.log('Response:', result.text);
202
+ console.log('Tool calls made:', result.toolCalls.length);
203
+ console.log('Tool results:', result.toolResults);
204
+ ```
205
+
206
+ #### Manual Tool Execution
207
+
208
+ ```typescript
209
+ // Step-by-step control over tool execution
210
+ const result = await RunAnywhere.generateWithTools(prompt, {
211
+ autoExecute: false, // Don't auto-execute
212
+ });
213
+
214
+ // Check if the LLM wants to call a tool
215
+ if (result.toolCalls.length > 0) {
216
+ const toolCall = result.toolCalls[0];
217
+ console.log(`LLM wants to call: ${toolCall.toolName}`);
218
+ console.log('Arguments:', toolCall.arguments);
219
+
220
+ // Execute manually
221
+ const toolResult = await RunAnywhere.executeTool(
222
+ toolCall.toolName,
223
+ toolCall.arguments
224
+ );
225
+
226
+ // Continue generation with the tool result
227
+ const finalResult = await RunAnywhere.continueWithToolResult(
228
+ prompt,
229
+ toolCall.toolName,
230
+ toolResult
231
+ );
232
+ console.log('Final response:', finalResult.text);
233
+ }
234
+ ```
235
+
236
+ #### Parse Tool Calls from Output
237
+
238
+ ```typescript
239
+ // Parse LLM output for tool call tags
240
+ const parsed = await RunAnywhere.parseToolCall(llmOutput);
241
+ if (parsed.hasToolCall) {
242
+ console.log('Tool:', parsed.toolName);
243
+ console.log('Args:', parsed.argumentsJson);
244
+ }
245
+ ```
246
+
247
+ #### Tool Calling Types
248
+
249
+ ```typescript
250
+ import type {
251
+ ToolDefinition,
252
+ ToolParameter,
253
+ ToolCall,
254
+ ToolResult,
255
+ ToolExecutor,
256
+ RegisteredTool,
257
+ ToolCallingOptions,
258
+ ToolCallingResult,
259
+ } from '@runanywhere/core';
260
+ ```
261
+
262
+ ---
263
+
264
+ ### Structured Output
265
+
266
+ Generate type-safe JSON responses with schema validation.
267
+
268
+ #### Generate Structured Data
269
+
270
+ ```typescript
271
+ import { RunAnywhere } from '@runanywhere/core';
272
+
273
+ // Generate JSON matching a schema
274
+ const result = await RunAnywhere.generateStructured(
275
+ {
276
+ type: 'object',
277
+ properties: {
278
+ name: { type: 'string', description: 'Product name' },
279
+ price: { type: 'number', description: 'Price in USD' },
280
+ inStock: { type: 'boolean' },
281
+ },
282
+ required: ['name', 'price'],
283
+ },
284
+ 'Extract the product info: The new Widget Pro costs $29.99 and is available now',
285
+ { temperature: 0.3, maxTokens: 256 }
286
+ );
287
+
288
+ console.log(result.data); // { name: "Widget Pro", price: 29.99, inStock: true }
289
+ ```
290
+
291
+ #### Extract Entities
292
+
293
+ ```typescript
294
+ const entities = await RunAnywhere.extractEntities(
295
+ 'John Smith from Acme Corp called about order #12345',
296
+ {
297
+ type: 'object',
298
+ properties: {
299
+ person: { type: 'string' },
300
+ company: { type: 'string' },
301
+ orderId: { type: 'string' },
302
+ },
303
+ }
304
+ );
305
+ // { entities: { person: "John Smith", company: "Acme Corp", orderId: "12345" }, confidence: 0.95 }
306
+ ```
307
+
308
+ #### Classify Text
309
+
310
+ ```typescript
311
+ const classification = await RunAnywhere.classify(
312
+ 'I love this product! Best purchase ever.',
313
+ ['positive', 'negative', 'neutral']
314
+ );
315
+ // { category: "positive", confidence: 0.97 }
316
+ ```
317
+
318
+ #### Structured Output Types
319
+
320
+ ```typescript
321
+ import type {
322
+ JSONSchema,
323
+ StructuredOutputOptions,
324
+ StructuredOutputResult,
325
+ EntityExtractionResult,
326
+ ClassificationResult,
327
+ } from '@runanywhere/core';
328
+ ```
329
+
330
+ ---
331
+
146
332
  ### EventBus
147
333
 
148
334
  Subscribe to SDK events for reactive updates.
@@ -335,6 +521,23 @@ import type {
335
521
  GenerationResult,
336
522
  PerformanceMetrics,
337
523
 
524
+ // Tool Calling
525
+ ToolDefinition,
526
+ ToolParameter,
527
+ ToolCall,
528
+ ToolResult,
529
+ ToolExecutor,
530
+ RegisteredTool,
531
+ ToolCallingOptions,
532
+ ToolCallingResult,
533
+
534
+ // Structured Output
535
+ JSONSchema,
536
+ StructuredOutputOptions,
537
+ StructuredOutputResult,
538
+ EntityExtractionResult,
539
+ ClassificationResult,
540
+
338
541
  // Voice
339
542
  STTOptions,
340
543
  STTResult,
@@ -367,6 +570,14 @@ packages/core/
367
570
  │ │ ├── Events/
368
571
  │ │ │ └── EventBus.ts # Event pub/sub
369
572
  │ │ └── Extensions/ # API method implementations
573
+ │ │ ├── RunAnywhere+TextGeneration.ts
574
+ │ │ ├── RunAnywhere+ToolCalling.ts
575
+ │ │ ├── RunAnywhere+StructuredOutput.ts
576
+ │ │ ├── RunAnywhere+STT.ts
577
+ │ │ ├── RunAnywhere+TTS.ts
578
+ │ │ ├── RunAnywhere+VAD.ts
579
+ │ │ ├── RunAnywhere+VoiceAgent.ts
580
+ │ │ └── ...
370
581
  │ ├── Foundation/
371
582
  │ │ ├── ErrorTypes/ # SDK errors
372
583
  │ │ ├── Initialization/ # Init state machine
@@ -383,10 +594,15 @@ packages/core/
383
594
  │ │ ├── FileSystem.ts # File ops
384
595
  │ │ └── Network/ # HTTP, telemetry
385
596
  │ ├── types/ # TypeScript types
597
+ │ │ ├── ToolCallingTypes.ts # Tool calling types
598
+ │ │ ├── StructuredOutputTypes.ts # Structured output types
599
+ │ │ └── ...
386
600
  │ └── native/ # Native module access
387
601
  ├── cpp/ # C++ HybridObject bridges
388
- ├── ios/ # Swift native module
389
- ├── android/ # Kotlin native module
602
+ ├── HybridRunAnywhereCore.cpp # Core native bridge
603
+ │ └── ToolCallingBridge.cpp # Tool calling C++ bridge
604
+ ├── ios/ # iOS native module
605
+ ├── android/ # Android native module
390
606
  └── nitrogen/ # Generated Nitro specs
391
607
  ```
392
608
 
@@ -35,6 +35,7 @@ Pod::Spec.new do |s|
35
35
  "HEADER_SEARCH_PATHS" => [
36
36
  "$(PODS_TARGET_SRCROOT)/cpp",
37
37
  "$(PODS_TARGET_SRCROOT)/cpp/bridges",
38
+ "$(PODS_TARGET_SRCROOT)/cpp/third_party",
38
39
  "$(PODS_TARGET_SRCROOT)/ios/Binaries/RACommons.xcframework/ios-arm64/RACommons.framework/Headers",
39
40
  "$(PODS_TARGET_SRCROOT)/ios/Binaries/RACommons.xcframework/ios-arm64_x86_64-simulator/RACommons.framework/Headers",
40
41
  "$(PODS_ROOT)/Headers/Public",
@@ -5,6 +5,19 @@ set(PACKAGE_NAME runanywherecore)
5
5
  set(CMAKE_VERBOSE_MAKEFILE ON)
6
6
  set(CMAKE_CXX_STANDARD 20)
7
7
 
8
+ # =============================================================================
9
+ # nlohmann/json - Header-only JSON library for robust JSON parsing
10
+ # Used by ToolCallingBridge for parsing tool call JSON from LLM output
11
+ # =============================================================================
12
+ include(FetchContent)
13
+ FetchContent_Declare(
14
+ nlohmann_json
15
+ GIT_REPOSITORY https://github.com/nlohmann/json.git
16
+ GIT_TAG v3.11.3
17
+ GIT_SHALLOW TRUE
18
+ )
19
+ FetchContent_MakeAvailable(nlohmann_json)
20
+
8
21
  # =============================================================================
9
22
  # 16KB Page Alignment for Android 15+ (API 35) Compliance
10
23
  # Required starting November 1, 2025 for Google Play submissions
@@ -23,8 +36,13 @@ set(RAC_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/main/include)
23
36
  # RACommons is REQUIRED - it's downloaded via Gradle downloadNativeLibs task
24
37
  # =============================================================================
25
38
  if(NOT EXISTS "${JNILIB_DIR}/librac_commons.so")
26
- message(FATAL_ERROR "[RunAnywhereCore] RACommons not found at ${JNILIB_DIR}/librac_commons.so\n"
27
- "Run: ./gradlew :runanywhere_core:downloadNativeLibs")
39
+ message(WARNING "[RunAnywhereCore] RACommons not found for ${ANDROID_ABI} at ${JNILIB_DIR}/librac_commons.so\n"
40
+ "This ABI will not be functional. To fix, run: ./gradlew :runanywhere_core:downloadNativeLibs\n"
41
+ "Or set reactNativeArchitectures=arm64-v8a in gradle.properties to skip this ABI.")
42
+ # Create a minimal stub library so the build can proceed for other ABIs
43
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/stub.cpp" "// Stub for missing ABI ${ANDROID_ABI}")
44
+ add_library(${PACKAGE_NAME} SHARED "${CMAKE_CURRENT_BINARY_DIR}/stub.cpp")
45
+ return()
28
46
  endif()
29
47
 
30
48
  add_library(rac_commons SHARED IMPORTED)
@@ -73,6 +91,7 @@ include_directories(
73
91
  "src/main/cpp"
74
92
  "../cpp"
75
93
  "../cpp/bridges"
94
+ "../cpp/third_party"
76
95
  "${CMAKE_SOURCE_DIR}/include"
77
96
  # RAC API headers from runanywhere-commons (flat access)
78
97
  "${RAC_INCLUDE_DIR}"
@@ -111,6 +130,9 @@ target_link_libraries(
111
130
  target_link_libraries(${PACKAGE_NAME} rac_commons)
112
131
  target_compile_definitions(${PACKAGE_NAME} PRIVATE HAS_RACOMMONS=1)
113
132
 
133
+ # Link nlohmann_json for ToolCallingBridge
134
+ target_link_libraries(${PACKAGE_NAME} nlohmann_json::nlohmann_json)
135
+
114
136
  # 16KB page alignment - MUST be on target for Android 15+ compliance
115
137
  target_link_options(${PACKAGE_NAME} PRIVATE -Wl,-z,max-page-size=16384)
116
138
 
@@ -38,9 +38,13 @@ def getExtOrDefault(name) {
38
38
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['RunAnywhereCore_' + name]
39
39
  }
40
40
 
41
- // Only arm64-v8a is supported - native libraries are only built for 64-bit ARM
41
+ // Supported ABIs - arm64-v8a for physical devices, x86_64 for emulators
42
+ // Can be overridden via gradle.properties: reactNativeArchitectures=arm64-v8a
42
43
  def reactNativeArchitectures() {
43
- return ["arm64-v8a"]
44
+ def value = rootProject.hasProperty("reactNativeArchitectures")
45
+ ? rootProject.property("reactNativeArchitectures")
46
+ : null
47
+ return value ? value.split(",").collect { it.trim() } : ["arm64-v8a", "x86_64"]
44
48
  }
45
49
 
46
50
  apply plugin: 'com.android.library'
@@ -113,7 +117,7 @@ android {
113
117
  targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
114
118
 
115
119
  ndk {
116
- abiFilters 'arm64-v8a'
120
+ abiFilters(*reactNativeArchitectures())
117
121
  }
118
122
 
119
123
  externalNativeBuild {
@@ -122,7 +126,7 @@ android {
122
126
  arguments "-DANDROID_STL=c++_shared",
123
127
  // Fix NitroModules prefab path - use app's build directory
124
128
  "-DREACT_NATIVE_NITRO_BUILD_DIR=${rootProject.buildDir}"
125
- abiFilters 'arm64-v8a'
129
+ abiFilters(*reactNativeArchitectures())
126
130
  }
127
131
  }
128
132
  }
@@ -220,11 +224,59 @@ task downloadNativeLibs {
220
224
  return
221
225
  }
222
226
 
223
- // Check if libs are already bundled (npm install case)
224
- def bundledLibsDir = file("${jniLibsDir}/arm64-v8a")
225
- def bundledLibs = bundledLibsDir.exists() ? bundledLibsDir.listFiles()?.findAll { it.name.endsWith(".so") } : []
226
- if (bundledLibs?.size() > 0) {
227
- logger.lifecycle("[RunAnywhereCore] Using bundled native libraries from npm package (${bundledLibs.size()} .so files)")
227
+ // Check if libs are already bundled for ALL requested ABIs (npm install case)
228
+ def requestedAbis = reactNativeArchitectures()
229
+ def allAbisBundled = requestedAbis.every { abi ->
230
+ def abiDir = file("${jniLibsDir}/${abi}")
231
+ def libs = abiDir.exists() ? abiDir.listFiles()?.findAll { it.name.endsWith(".so") } : []
232
+ return libs?.size() > 0
233
+ }
234
+ if (allAbisBundled) {
235
+ logger.lifecycle("[RunAnywhereCore] ✅ Using bundled native libraries from npm package for ABIs: ${requestedAbis.join(', ')}")
236
+ return
237
+ }
238
+ // Check if at least arm64-v8a is bundled (partial bundle - need to download missing ABIs)
239
+ def arm64Dir = file("${jniLibsDir}/arm64-v8a")
240
+ def arm64Bundled = arm64Dir.exists() && arm64Dir.listFiles()?.any { it.name.endsWith(".so") }
241
+ if (arm64Bundled) {
242
+ def missingAbis = requestedAbis.findAll { abi ->
243
+ def abiDir = file("${jniLibsDir}/${abi}")
244
+ def libs = abiDir.exists() ? abiDir.listFiles()?.findAll { it.name.endsWith(".so") } : []
245
+ return !libs || libs.size() == 0
246
+ }
247
+ if (missingAbis.size() > 0) {
248
+ logger.lifecycle("[RunAnywhereCore] ⚠️ Bundled libs found for arm64-v8a but missing for: ${missingAbis.join(', ')}")
249
+ logger.lifecycle("[RunAnywhereCore] Attempting to download missing ABIs from GitHub releases...")
250
+ // Try to download and extract only missing ABIs (don't delete existing bundled libs)
251
+ try {
252
+ def commonsUrl = "https://github.com/${githubOrg}/${commonsRepo}/releases/download/commons-v${commonsVersion}/RACommons-android-v${commonsVersion}.zip"
253
+ def tempZip = file("${downloadedLibsDir}/RACommons-supplement.zip")
254
+ downloadedLibsDir.mkdirs()
255
+ new URL(commonsUrl).withInputStream { input ->
256
+ tempZip.withOutputStream { output -> output << input }
257
+ }
258
+ copy {
259
+ from zipTree(tempZip)
260
+ into jniLibsDir
261
+ exclude "**/libc++_shared.so"
262
+ eachFile { fileCopyDetails ->
263
+ def pathString = fileCopyDetails.relativePath.pathString
264
+ if (pathString.startsWith("jniLibs/") && pathString.endsWith(".so")) {
265
+ def newPath = pathString.replaceFirst("^jniLibs/", "")
266
+ fileCopyDetails.relativePath = new RelativePath(true, newPath.split("/"))
267
+ } else if (!pathString.endsWith(".so")) {
268
+ fileCopyDetails.exclude()
269
+ }
270
+ }
271
+ includeEmptyDirs = false
272
+ }
273
+ tempZip.delete()
274
+ logger.lifecycle("[RunAnywhereCore] ✅ Downloaded missing ABIs successfully")
275
+ } catch (Exception e) {
276
+ logger.warn("[RunAnywhereCore] ⚠️ Could not download missing ABIs: ${e.message}")
277
+ logger.warn("[RunAnywhereCore] Building with available ABIs only (arm64-v8a)")
278
+ }
279
+ }
228
280
  return
229
281
  }
230
282
 
@@ -2,6 +2,7 @@
2
2
  #include <string>
3
3
  #include <android/log.h>
4
4
  #include "runanywherecoreOnLoad.hpp"
5
+ #include "PlatformDownloadBridge.h"
5
6
 
6
7
  #define LOG_TAG "ArchiveJNI"
7
8
  #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
@@ -35,6 +36,8 @@ jmethodID g_getCoreCountMethod = nullptr;
35
36
  jmethodID g_getArchitectureMethod = nullptr;
36
37
  jmethodID g_getGPUFamilyMethod = nullptr;
37
38
  jmethodID g_isTabletMethod = nullptr;
39
+ jmethodID g_httpDownloadMethod = nullptr;
40
+ jmethodID g_httpDownloadCancelMethod = nullptr;
38
41
  // HttpResponse field IDs
39
42
  jfieldID g_httpResponse_successField = nullptr;
40
43
  jfieldID g_httpResponse_statusCodeField = nullptr;
@@ -101,11 +104,14 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
101
104
  g_getArchitectureMethod = env->GetStaticMethodID(g_platformAdapterBridgeClass, "getArchitecture", "()Ljava/lang/String;");
102
105
  g_getGPUFamilyMethod = env->GetStaticMethodID(g_platformAdapterBridgeClass, "getGPUFamily", "()Ljava/lang/String;");
103
106
  g_isTabletMethod = env->GetStaticMethodID(g_platformAdapterBridgeClass, "isTablet", "()Z");
107
+ g_httpDownloadMethod = env->GetStaticMethodID(g_platformAdapterBridgeClass, "httpDownload", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
108
+ g_httpDownloadCancelMethod = env->GetStaticMethodID(g_platformAdapterBridgeClass, "httpDownloadCancel", "(Ljava/lang/String;)Z");
104
109
 
105
- if (g_secureSetMethod && g_secureGetMethod && g_getPersistentDeviceUUIDMethod &&
110
+ if (g_secureSetMethod && g_secureGetMethod && g_getPersistentDeviceUUIDMethod &&
106
111
  g_getDeviceModelMethod && g_getOSVersionMethod && g_getChipNameMethod &&
107
- g_getTotalMemoryMethod && g_getAvailableMemoryMethod && g_getCoreCountMethod &&
108
- g_getArchitectureMethod && g_getGPUFamilyMethod && g_isTabletMethod) {
112
+ g_getTotalMemoryMethod && g_getAvailableMemoryMethod && g_getCoreCountMethod &&
113
+ g_getArchitectureMethod && g_getGPUFamilyMethod && g_isTabletMethod &&
114
+ g_httpDownloadMethod && g_httpDownloadCancelMethod) {
109
115
  LOGI("PlatformAdapterBridge class and methods cached successfully");
110
116
  } else {
111
117
  LOGE("Failed to cache some PlatformAdapterBridge methods");
@@ -269,3 +275,45 @@ extern "C" bool ArchiveUtility_extractAndroid(const char* archivePath, const cha
269
275
 
270
276
  return result == JNI_TRUE;
271
277
  }
278
+
279
+ // =============================================================================
280
+ // HTTP Download Callback Reporting (from Kotlin to C++)
281
+ // =============================================================================
282
+
283
+ static std::string jstringToStdString(JNIEnv* env, jstring value) {
284
+ if (value == nullptr) {
285
+ return "";
286
+ }
287
+ const char* chars = env->GetStringUTFChars(value, nullptr);
288
+ std::string result = chars ? chars : "";
289
+ if (chars) {
290
+ env->ReleaseStringUTFChars(value, chars);
291
+ }
292
+ return result;
293
+ }
294
+
295
+ extern "C" JNIEXPORT jint JNICALL
296
+ Java_com_margelo_nitro_runanywhere_PlatformAdapterBridge_nativeHttpDownloadReportProgress(
297
+ JNIEnv* env, jclass clazz, jstring taskId, jlong downloadedBytes, jlong totalBytes) {
298
+ (void)clazz;
299
+ std::string task = jstringToStdString(env, taskId);
300
+ return RunAnywhereHttpDownloadReportProgress(task.c_str(),
301
+ static_cast<int64_t>(downloadedBytes),
302
+ static_cast<int64_t>(totalBytes));
303
+ }
304
+
305
+ extern "C" JNIEXPORT jint JNICALL
306
+ Java_com_margelo_nitro_runanywhere_PlatformAdapterBridge_nativeHttpDownloadReportComplete(
307
+ JNIEnv* env, jclass clazz, jstring taskId, jint result, jstring downloadedPath) {
308
+ (void)clazz;
309
+ std::string task = jstringToStdString(env, taskId);
310
+ if (downloadedPath == nullptr) {
311
+ return RunAnywhereHttpDownloadReportComplete(task.c_str(),
312
+ static_cast<int>(result),
313
+ nullptr);
314
+ }
315
+ std::string path = jstringToStdString(env, downloadedPath);
316
+ return RunAnywhereHttpDownloadReportComplete(task.c_str(),
317
+ static_cast<int>(result),
318
+ path.c_str());
319
+ }