Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a596052
Flutter: offload blocking inference to worker isolates, fix download …
Siddhesh2377 Jun 17, 2026
fb5811e
telemetry: report OS platform (not 'flutter'), publish embeddings eve…
Siddhesh2377 Jun 18, 2026
f5dec89
telemetry: populate V2 fields via properties carrier — embeddings dim…
Siddhesh2377 Jun 18, 2026
baadc17
telemetry: VLM token metrics + LoRA adapter_id/base_model_id via prop…
Siddhesh2377 Jun 18, 2026
85c0df6
telemetry: attach sink in Phase 1 (fixes dropped system events), emit…
Siddhesh2377 Jun 18, 2026
2ea3ab0
Flutter: wire voice-agent mic driver, run turns off UI isolate, fix t…
Siddhesh2377 Jun 21, 2026
55e7f7e
commons: telemetry field population across modalities + env gate, VAD…
Siddhesh2377 Jun 21, 2026
2ea3547
web: export rac_auth_get_access_token for WASM telemetry auth
Siddhesh2377 Jun 21, 2026
8c8fba2
RN example app v2 redesign + LLM streaming, IME padding, and icon fixes
Siddhesh2377 Jun 21, 2026
fa1cd6a
RN chat: Android-style composer (tool button + prompt suggestions), L…
Siddhesh2377 Jun 21, 2026
35389a9
web: fix model discovery (WASM framework exports + models.hydrated UI…
Siddhesh2377 Jun 22, 2026
6e56118
voice: required VAD model card across KT/Flutter/RN, RN mic driver + …
Siddhesh2377 Jun 23, 2026
55e0fc1
android example: bump lifecycle 2.11.0, composeBom 2026.06.00, okhttp…
Siddhesh2377 Jun 23, 2026
b4fedfd
fixes
shubhammalhotra28 Jun 24, 2026
bf57441
Merge branch 'common' into integrate-mywork
shubhammalhotra28 Jun 25, 2026
698a0b4
Merge branch 'fixes-ios' into integrate-mywork
shubhammalhotra28 Jun 25, 2026
8c65b8d
voice_agent: restore null guard on llm.text in proto_abi turn-complet…
shubhammalhotra28 Jun 25, 2026
5e2914b
rn: reconcile yarn.lock react resolution to pinned 19.2.3
shubhammalhotra28 Jun 25, 2026
1259908
works
shubhammalhotra28 Jun 26, 2026
9495a69
flutter-ios fixes
shubhammalhotra28 Jun 26, 2026
4711d56
fixing tthe ci/cd
shubhammalhotra28 Jun 26, 2026
4fd3a23
rn: refresh nested standalone yarn.lock for react 19.2.7
shubhammalhotra28 Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/android/RunAnywhereAI/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ dependencies {
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.navigation.compose)
implementation(libs.kotlinx.serialization.json)
// files(...) AARs carry no POM; declare coroutines 1.11.0 directly so it outranks
// the older transitive core from androidx (SDK is compiled against 1.11.0).
implementation(libs.kotlinx.coroutines.android)
implementation(libs.proto.wire.runtime)
testImplementation(libs.junit)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ class RunAnywhereApplication : Application() {
RunAnywhere.initialize(
apiKey = BuildConfig.RUNANYWHERE_API_KEY,
baseURL = BuildConfig.RUNANYWHERE_BASE_URL,
environment = SDKEnvironment.SDK_ENVIRONMENT_PRODUCTION,
// STAGING (not PRODUCTION) so the railway *development* backend in
// local.properties is honored and telemetry lands — matches the
// Flutter example. PRODUCTION expects a production backend/auth and
// also disables console logging.
environment = SDKEnvironment.SDK_ENVIRONMENT_STAGING,
)
// Production env disables SDK console logging entirely; without this
// debug builds emit zero SDK logs to logcat, which makes on-device
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ fun VoiceScreen() {
viewModel(key = "voice-stt", factory = ModelSelectionViewModel.Factory(ModelSelectionContext.STT))
val ttsVm: ModelSelectionViewModel =
viewModel(key = "voice-tts", factory = ModelSelectionViewModel.Factory(ModelSelectionContext.TTS))
val vadVm: ModelSelectionViewModel =
viewModel(key = "voice-vad", factory = ModelSelectionViewModel.Factory(ModelSelectionContext.VAD))
var sheet by remember { mutableStateOf<ModelSelectionViewModel?>(null) }
val listState = rememberLazyListState()

val llmName = GlobalState.model.loaded?.name
val sttName = sttVm.state.models.firstOrNull { it.id == sttVm.state.currentModelId }?.name
val ttsVoice = ttsVm.state.models.firstOrNull { it.id == ttsVm.state.currentModelId }
val ready = llmName != null && sttName != null && ttsVoice != null
val vadName = vadVm.state.models.firstOrNull { it.id == vadVm.state.currentModelId }?.name
val ready = llmName != null && sttName != null && ttsVoice != null && vadName != null

val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission(),
Expand Down Expand Up @@ -110,7 +113,9 @@ fun VoiceScreen() {
SetupRow(RACIcons.Outline.Brain, "Speech to text", sttName, onClick = { sheet = sttVm })
Divider()
SetupRow(RACIcons.Outline.Robot, "Voice", ttsVoice?.name, onClick = { sheet = ttsVm })
}
Divider()
SetupRow(RACIcons.Outline.Activity, "Voice activity (VAD)", vadName, onClick = { sheet = vadVm })
}
}

Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) {
Expand Down
6 changes: 3 additions & 3 deletions examples/android/RunAnywhereAI/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ kotlin = "2.4.0"
# AndroidX core
coreKtx = "1.19.0"
activityCompose = "1.13.0"
lifecycleRuntimeKtx = "2.10.0"
lifecycleRuntimeKtx = "2.11.0"

# Security
securityCrypto = "1.1.0"

# Compose
composeBom = "2026.05.01"
composeBom = "2026.06.00"

# Navigation & serialization
navigationCompose = "2.9.8"
Expand All @@ -37,7 +37,7 @@ espressoCore = "3.7.0"
wire = "6.4.0"

# Networking
okhttp = "5.3.2"
okhttp = "5.4.0"

# Document parsing (RAG ingestion)
pdfbox = "2.0.27.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
Expand Down
3 changes: 3 additions & 0 deletions examples/flutter/RunAnywhereAI/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ android/settings.gradle.kts

# FVM Version Cache
.fvm/

# Local --dart-define secrets (API key / base URL)
dart_defines.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
android:label="RunAnywhere AI"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

MANIFEST="examples/flutter/RunAnywhereAI/android/app/src/main/AndroidManifest.xml"

echo "Checking $MANIFEST"
rg -n 'extractNativeLibs|uses-native-library|libcdsprpc\.so' "$MANIFEST"

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 289


Fix extractNativeLibs attribute value in AndroidManifest.xml.

The file contains both required entries, but extractNativeLibs is set to "false" (line 12) when the coding guidelines require it to be "true". The <uses-native-library> entry for libcdsprpc.so is correct (line 15). Change line 12 to use android:extractNativeLibs="true".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/flutter/RunAnywhereAI/android/app/src/main/AndroidManifest.xml` at
line 11, Locate the android:extractNativeLibs attribute in the
AndroidManifest.xml file and change its value from "false" to "true" to comply
with the coding guidelines. This attribute controls whether native libraries
should be extracted from the APK, and it needs to be enabled for proper native
library handling.

Source: Coding guidelines

android:extractNativeLibs="false"
android:enableOnBackInvokedCallback="true">
<!-- Declare vendor public library for Genie NPU (Qualcomm FastRPC DSP communication) -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,14 @@ public static void registerWith(@NonNull FlutterEngine flutterEngine) {
Log.e(TAG, "Error registering plugin image_picker_android, io.flutter.plugins.imagepicker.ImagePickerPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.github.dart_lang.jni.JniPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin jni, com.github.dart_lang.jni.JniPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.github.dart_lang.jni_flutter.JniFlutterPlugin());
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin jni_flutter, com.github.dart_lang.jni_flutter.JniFlutterPlugin", e);
Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
}
try {
flutterEngine.getPlugins().add(new dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin());
flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin());
} catch (Exception e) {
Log.e(TAG, "Error registering plugin package_info_plus, dev.fluttercommunity.plus.packageinfo.PackageInfoPlugin", e);
Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e);
}
try {
flutterEngine.getPlugins().add(new com.baseflow.permissionhandler.PermissionHandlerPlugin());
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:statusBarColor">@android:color/black</item>
<item name="android:windowLightStatusBar">false</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Expand All @@ -14,5 +16,7 @@
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
<item name="android:statusBarColor">@android:color/black</item>
<item name="android:windowLightStatusBar">false</item>
</style>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:statusBarColor">@android:color/white</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<!-- Theme applied to the Android Application as a whole. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
<item name="android:statusBarColor">@android:color/white</item>
<item name="android:windowLightStatusBar">true</item>
</style>
</resources>
4 changes: 2 additions & 2 deletions examples/flutter/RunAnywhereAI/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '2.1.21'
ext.kotlin_version = '2.2.20'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:8.9.1'
classpath 'com.android.tools.build:gradle:8.11.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
4 changes: 2 additions & 2 deletions examples/flutter/RunAnywhereAI/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.9.1" apply false
id "org.jetbrains.kotlin.android" version "2.1.21" apply false
id "com.android.application" version "8.11.1" apply false
id "org.jetbrains.kotlin.android" version "2.2.20" apply false
}

include ":app"
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict>
</plist>
9 changes: 6 additions & 3 deletions examples/flutter/RunAnywhereAI/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import UIKit
import Flutter
import UIKit

@main
@objc class AppDelegate: FlutterAppDelegate {
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
@import package_info_plus;
#endif

#if __has_include(<path_provider_foundation/PathProviderPlugin.h>)
#import <path_provider_foundation/PathProviderPlugin.h>
#else
@import path_provider_foundation;
#endif

#if __has_include(<permission_handler_apple/PermissionHandlerPlugin.h>)
#import <permission_handler_apple/PermissionHandlerPlugin.h>
#else
Expand Down Expand Up @@ -106,6 +112,7 @@ + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
[FlutterSecureStorageDarwinPlugin registerWithRegistrar:[registry registrarForPlugin:@"FlutterSecureStorageDarwinPlugin"]];
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
[FPPPackageInfoPlusPlugin registerWithRegistrar:[registry registrarForPlugin:@"FPPPackageInfoPlusPlugin"]];
[PathProviderPlugin registerWithRegistrar:[registry registrarForPlugin:@"PathProviderPlugin"]];
[PermissionHandlerPlugin registerWithRegistrar:[registry registrarForPlugin:@"PermissionHandlerPlugin"]];
[RecordIosPlugin registerWithRegistrar:[registry registrarForPlugin:@"RecordIosPlugin"]];
[RunAnywherePlugin registerWithRegistrar:[registry registrarForPlugin:@"RunAnywherePlugin"]];
Expand Down
21 changes: 21 additions & 0 deletions examples/flutter/RunAnywhereAI/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@
<string>This app needs microphone access for voice assistant features.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app needs speech recognition for voice assistant features.</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
Expand Down
41 changes: 32 additions & 9 deletions examples/flutter/RunAnywhereAI/lib/app/content_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,41 @@ class ContentView extends StatefulWidget {
class _ContentViewState extends State<ContentView> {
int _selectedTab = 0;

// Tab pages matching iOS structure.
final List<Widget> _pages = const [
ChatInterfaceView(), // Tab 0: Chat (LLM)
VisionHubView(), // Tab 1: Vision (VLM)
VoiceAssistantView(), // Tab 2: Voice Assistant (STT + LLM + TTS)
MoreView(), // Tab 3: More hub
CombinedSettingsView(), // Tab 4: Settings
];
// Tabs are built lazily on first visit and kept alive afterwards. A hidden
// tab's initState / view-model work (animations, event-bus subscriptions,
// periodic refreshes) must not run until the user selects that tab.
// IndexedStack still preserves each tab's state once it has been built.
final Set<int> _visitedTabs = {0};

Widget _buildTab(int index) {
switch (index) {
case 0:
return const ChatInterfaceView(); // Chat (LLM)
case 1:
return const VisionHubView(); // Vision (VLM)
case 2:
return const VoiceAssistantView(); // Voice Assistant (STT + LLM + TTS)
case 3:
return const MoreView(); // More hub
case 4:
return const CombinedSettingsView(); // Settings
default:
return const SizedBox.shrink();
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(index: _selectedTab, children: _pages),
body: IndexedStack(
index: _selectedTab,
children: List.generate(
5,
(index) => _visitedTabs.contains(index)
? _buildTab(index)
: const SizedBox.shrink(),
),
),
bottomNavigationBar: NavigationBar(
selectedIndex: _selectedTab,
// B-FL-14-002: explicit height + vertical padding so the
Expand All @@ -43,6 +65,7 @@ class _ContentViewState extends State<ContentView> {
onDestinationSelected: (index) {
setState(() {
_selectedTab = index;
_visitedTabs.add(index);
});
},
destinations: const [
Expand Down
19 changes: 11 additions & 8 deletions examples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {

await _registerBackends();

final customApiKey = await KeychainHelper.loadString(KeychainKeys.apiKey);
final customBaseURL = await KeychainHelper.loadString(
KeychainKeys.baseURL,
);
final customApiKey =
await KeychainHelper.loadString(KeychainKeys.apiKey) ??
DefaultConfig.runanywhereApiKey;
final customBaseURL =
await KeychainHelper.loadString(KeychainKeys.baseURL) ??
DefaultConfig.runanywhereBaseUrl;
final hasCustomConfig =
customApiKey != null &&
customApiKey.isNotEmpty &&
customBaseURL != null &&
customBaseURL.isNotEmpty &&
!_looksLikePlaceholder(customApiKey) &&
!_looksLikePlaceholder(customBaseURL);
Expand All @@ -73,9 +73,12 @@ class _RunAnywhereAIAppState extends State<RunAnywhereAIApp> {
await RunAnywhere.initialize(
apiKey: customApiKey,
baseURL: normalizedURL,
environment: SDKEnvironment.SDK_ENVIRONMENT_PRODUCTION,
// Staging (not Production) so the custom base URL is honored AND
// local logging stays on — Production sets enableLocalLogging:false,
// hiding all SDK/telemetry logs. Development would ignore baseURL.
environment: SDKEnvironment.SDK_ENVIRONMENT_STAGING,
);
debugPrint('✅ SDK initialized with CUSTOM configuration (production)');
debugPrint('✅ SDK initialized with CUSTOM configuration (staging)');
} else {
await RunAnywhere.initialize();
debugPrint('✅ SDK initialized in DEVELOPMENT mode');
Expand Down
Loading
Loading