Skip to content

Conversation

@sanchitmonga22
Copy link
Contributor

@sanchitmonga22 sanchitmonga22 commented Nov 29, 2025

…ponding ViewModels

  • Added SpeechToTextScreen and TextToSpeechScreen components, mirroring iOS functionality.
  • Introduced SpeechToTextViewModel and TextToSpeechViewModel for managing UI state and interactions.
  • Enhanced AppNavigation to include new STT and TTS routes, replacing previous Storage functionality.
  • Updated SettingsScreen to combine settings and storage management, aligning with iOS design.
  • Refactored BottomNavigationBar to match iOS tab structure, ensuring consistent user experience across platforms.
  • Integrated model selection dialogs for STT and TTS, improving user interaction for model management.

This commit enhances the overall functionality and user experience of the application, aligning with the iOS architecture.

Description

Brief description of the changes made.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Refactoring

Testing

  • Tests pass locally
  • Tested on Macbook if swift changes
  • Tested on Tablet/iPad if swift changes
  • Added/updated tests for changes

Labels

Please add the appropriate label(s):

  • iOS SDK - Changes to iOS/Swift SDK
  • Android SDK - Changes to Android/Kotlin SDK
  • iOS Sample - Changes to iOS example app
  • Android Sample - Changes to Android example app

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Documentation updated (if needed)

Screenshots - Attach all the relevant UI changes screenshots for iOS/Android and MacOS/Tablet/large screen sizes

Summary by CodeRabbit

  • New Features

    • Added Speech-to-Text (STT) and Text-to-Speech (TTS) screens with model selection and real-time processing capabilities.
    • Added conversation history management with list view, detailed analytics, and search functionality.
    • Enhanced settings with API key management, storage overview, model management, and generation parameter controls.
    • Added voice assistant setup flow requiring model coordination before use.
    • Added token counting and generation metrics tracking.
  • Improvements

    • Redesigned bottom navigation: replaced Storage and Quiz tabs with STT and TTS.
    • Completely rebuilt settings interface with organized configuration sections.

✏️ Tip: You can customize this high-level summary in your review settings.


Important

This PR updates the Android SDK with new STT and TTS UI components, aligns navigation with iOS, and integrates ONNX Runtime for native ML operations.

  • UI Components:
    • Added SpeechToTextScreen and TextToSpeechScreen components for Android, mirroring iOS functionality.
    • Updated AppNavigation to include new STT and TTS routes, replacing previous Storage functionality.
    • Refactored BottomNavigationBar to match iOS tab structure.
  • ViewModels:
    • Introduced SpeechToTextViewModel and TextToSpeechViewModel for managing UI state and interactions.
  • Settings:
    • Updated SettingsScreen to combine settings and storage management, aligning with iOS design.
  • Model Management:
    • Integrated model selection dialogs for STT and TTS.
  • Backend:
    • Added ONNX Runtime backend support for native ML operations in ONNXCoreService.kt.
  • Misc:
    • Removed auto-generated Flutter config file Generated.xcconfig.

This description was created by Ellipsis for 14ae81c. You can customize this summary. It will automatically update as commits are pushed.


Greptile Overview

Greptile Summary

This PR successfully implements Speech-to-Text and Text-to-Speech features for Android, mirroring the iOS implementation. The changes introduce new UI screens (SpeechToTextScreen, TextToSpeechScreen) with corresponding ViewModels, along with foundational ONNX Runtime backend support through a new runanywhere-core-onnx module.

Key Changes:

  • Added STT screen with batch/live transcription modes and recording controls
  • Added TTS screen with voice selection, speed/pitch adjustment, and playback features
  • Restructured bottom navigation to match iOS (5 tabs: Chat, STT, TTS, Voice, Settings)
  • Enhanced Settings screen to combine configuration and storage management
  • Introduced ONNX Runtime backend with JNI bridge for native inference operations
  • Added architecture documentation for Swift SDK design patterns

Implementation Notes:

  • ViewModels currently use mock data with clear TODO comments marking SDK integration points
  • ONNX backend implementation is thread-safe with proper mutex locking and error handling
  • UI components follow iOS design patterns for cross-platform consistency

Issues Found:

  • Flutter auto-generated config file should not be committed (already flagged in previous review threads)

Confidence Score: 4/5

  • This PR is safe to merge with minor cleanup recommended
  • The implementation is well-structured with clean architecture and proper separation of concerns. ViewModels use mock data with clear SDK integration points, making it safe for UI development. The ONNX backend code is properly implemented with thread safety and error handling. One issue from previous review threads (Flutter generated file) remains but doesn't affect functionality. Code follows repository conventions and includes comprehensive documentation.
  • examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig should be removed and added to .gitignore as previously noted

Important Files Changed

File Analysis

Filename Score Overview
examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig 1/5 Auto-generated Flutter config file with developer-specific paths - should not be committed to version control (already flagged in previous threads)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt 5/5 New STT screen with batch/live modes, recording button, model status banner - well-structured UI matching iOS design
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechScreen.kt 5/5 New TTS screen with voice selection, speed/pitch controls, playback features - comprehensive UI implementation matching iOS
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt 4/5 Settings ViewModel enhanced with storage management and routing policy - contains logical error in model deletion size calculation (uses original list instead of filtered)
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt 5/5 New ONNX Runtime backend implementation with thread-safe operations - well-designed with proper mutex locking and error handling

Sequence Diagram

sequenceDiagram
    participant User
    participant UI as STT/TTS Screen
    participant ViewModel as STT/TTS ViewModel
    participant SDK as RunAnywhere SDK
    participant ONNX as ONNXCoreService
    participant JNI as RunAnywhereBridge
    participant Native as Native C++ Backend

    Note over User,Native: Model Selection Flow
    User->>UI: Select Model
    UI->>ViewModel: loadModel(name, id)
    ViewModel->>ViewModel: Update state (PROCESSING)
    ViewModel->>SDK: Initialize STT/TTS Component
    SDK->>ONNX: loadSTTModel/loadTTSModel
    ONNX->>JNI: nativeSTTLoadModel/nativeTTSLoadModel
    JNI->>Native: Load ONNX model
    Native-->>JNI: Success
    JNI-->>ONNX: ResultCode
    ONNX-->>SDK: Model loaded
    SDK-->>ViewModel: Component ready
    ViewModel->>ViewModel: Update state (IDLE, model loaded)
    ViewModel-->>UI: UI state updated
    UI-->>User: Show model loaded banner

    Note over User,Native: STT Recording & Transcription Flow
    User->>UI: Tap record button
    UI->>ViewModel: toggleRecording()
    ViewModel->>ViewModel: startRecording()
    ViewModel->>ViewModel: Update state (RECORDING)
    ViewModel-->>UI: UI shows recording animation
    User->>UI: Tap stop button
    UI->>ViewModel: toggleRecording()
    ViewModel->>ViewModel: stopRecording()
    ViewModel->>ViewModel: Update state (PROCESSING)
    ViewModel->>SDK: transcribe(audioData)
    SDK->>ONNX: transcribe(samples, sampleRate)
    ONNX->>JNI: nativeSTTTranscribe
    JNI->>Native: Process audio with ONNX
    Native-->>JNI: Transcription text
    JNI-->>ONNX: String result
    ONNX-->>SDK: Transcription
    SDK-->>ViewModel: Transcription result
    ViewModel->>ViewModel: Update state (IDLE, transcription)
    ViewModel-->>UI: Display transcription
    UI-->>User: Show transcribed text

    Note over User,Native: TTS Generation & Playback Flow
    User->>UI: Enter text and tap generate
    UI->>ViewModel: generateSpeech()
    ViewModel->>ViewModel: Update state (GENERATING)
    ViewModel->>SDK: synthesize(text)
    SDK->>ONNX: synthesize(text, voiceId, speed, pitch)
    ONNX->>JNI: nativeTTSSynthesize
    JNI->>Native: Generate audio with ONNX
    Native-->>JNI: Audio samples + sample rate
    JNI-->>ONNX: NativeTTSSynthesisResult
    ONNX-->>SDK: Audio data
    SDK-->>ViewModel: Audio ready
    ViewModel->>ViewModel: Update state (audio generated)
    ViewModel-->>UI: Enable playback controls
    User->>UI: Tap play button
    UI->>ViewModel: togglePlayback()
    ViewModel->>ViewModel: startPlayback()
    ViewModel-->>UI: Show playback progress
    UI-->>User: Play audio

    Note over User,Native: Settings & Storage Management
    User->>UI: Navigate to Settings
    UI->>ViewModel: Load settings
    ViewModel->>SDK: Get stored models
    SDK-->>ViewModel: Model list
    ViewModel->>ViewModel: Calculate storage sizes
    ViewModel-->>UI: Display storage overview
    User->>UI: Delete model
    UI->>ViewModel: deleteModel(modelId)
    ViewModel->>SDK: Delete model files
    SDK-->>ViewModel: Deletion complete
    ViewModel->>ViewModel: Update model list & sizes
    ViewModel-->>UI: Refresh UI
Loading

…ponding ViewModels

- Added SpeechToTextScreen and TextToSpeechScreen components, mirroring iOS functionality.
- Introduced SpeechToTextViewModel and TextToSpeechViewModel for managing UI state and interactions.
- Enhanced AppNavigation to include new STT and TTS routes, replacing previous Storage functionality.
- Updated SettingsScreen to combine settings and storage management, aligning with iOS design.
- Refactored BottomNavigationBar to match iOS tab structure, ensuring consistent user experience across platforms.
- Integrated model selection dialogs for STT and TTS, improving user interaction for model management.

This commit enhances the overall functionality and user experience of the application, aligning with the iOS architecture.
@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR significantly expands the RunAnywhere Kotlin SDK with a new native ONNX module via JNI integration and substantially refactors the Android RunAnywhereAI app UI and state management. It adds STT/TTS screens, reorganizes navigation, enriches settings and voice assistant flows, and introduces new public SDK APIs for model loading, token counting, and generation result modeling.

Changes

Cohort / File(s) Summary
Android UI Screens
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatScreen.kt, presentation/settings/SettingsScreen.kt, presentation/navigation/AppNavigation.kt, presentation/voice/TranscriptionScreen.kt, presentation/voice/VoiceAssistantScreen.kt, presentation/stt/SpeechToTextScreen.kt, presentation/tts/TextToSpeechScreen.kt
Major UI refactoring: adds ConversationListSheet and ChatDetailsSheet for chat management; replaces SettingsScreen with comprehensive multi-section settings UI; restructures navigation with STT/TTS tabs replacing Storage/Quiz; refactors TranscriptionScreen naming (isRecording → isTranscribing); redesigns VoiceAssistantScreen with two-phase setup flow and model selection dialogs; introduces new SpeechToTextScreen and TextToSpeechScreen with recording/synthesis UI.
Android MainActivity & Theme
presentation/MainActivity.kt, ui/theme/Color.kt
Removes Hilt AndroidEntryPoint annotation and import from MainActivity; deletes unused public color constants from Color.kt.
Android ViewModels
presentation/chat/ChatViewModel.kt, presentation/settings/SettingsViewModel.kt, presentation/storage/StorageViewModel.kt, presentation/voice/TranscriptionViewModel.kt, presentation/voice/VoiceAssistantViewModel.kt, presentation/stt/SpeechToTextViewModel.kt, presentation/tts/TextToSpeechViewModel.kt
Implements comprehensive MVVM state management: ChatViewModel removes Hilt comment; SettingsViewModel adds routing policy, generation config, API key, and storage management; StorageViewModel adds model info and storage state tracking; TranscriptionViewModel adds speaker diarization, transcript segments, and export/clipboard functionality; VoiceAssistantViewModel introduces model lifecycle tracking (NOT_LOADED/LOADING/LOADED/ERROR states) and VoiceUiState; SpeechToTextViewModel adds STTMode/RecordingState enums and recording lifecycle; TextToSpeechViewModel adds TTSUiState and TTS synthesis/playback control.
Kotlin SDK—Native Core ONNX Module
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts, proguard-rules.pro, .gitignore, VERSION, scripts/download-native-libs.sh
Introduces new runanywhere-core-onnx Gradle module for JNI-based ONNX runtime integration with remote/local native library download, ProGuard rules to preserve JNI bridge and public service APIs, version tracking, and Maven publication configuration.
Kotlin SDK—JNI Bridge & Native Service
modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt, ONNXCoreService.kt
Implements RunAnywhereBridge JNI object with thread-safe native library loading and comprehensive external JNI functions for backend lifecycle, STT/TTS/VAD/Embedding operations; implements ONNXCoreService wrapping the JNI bridge with mutex-guarded operations, model state tracking, and error handling.
Kotlin SDK—Native Bridge Interfaces & Models
src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt, BridgeResults.kt, Capability.kt
Introduces NativeCoreService interface defining unified API for native backends; adds NativeTTSSynthesisResult and NativeVADResult data classes; introduces NativeCapability, NativeDeviceType, and NativeResultCode enums for native interop.
Kotlin SDK—Public API Expansion
src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt, public/models/GenerationResult.kt, components/stt/STTComponent.kt, components/stt/STTModels.kt, generation/TokenCounter.kt
Expands RunAnywhereSDK public interface with STT/TTS model loading, token counting; adds GenerationResult, HardwareAcceleration, and StructuredOutputValidation models with metrics and streaming support; introduces TokenCounter singleton for token estimation; adds STTMode enum and supportsStreaming/recommendedMode properties to STTComponent.
Android Build Configuration
examples/android/RunAnywhereAI/app/build.gradle.kts, settings.gradle.kts, sdk/runanywhere-kotlin/settings.gradle.kts
Narrows supported ABIs to arm64-v8a only; adds runanywhere-core-onnx module dependency and include in settings.
Build & Project Structure
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/.gitignore, VERSION
Adds gitignore rules for downloaded native libraries and build artifacts; adds version metadata (0.0.1-dev.e2ac4eb).
Flutter & Documentation
examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig, flutter_export_environment.sh, sdk/runanywhere-swift/ARCHITECTURE.md, .gitignore
Deletes Flutter iOS generated configuration files; adds Swift SDK architecture documentation; expands root gitignore to exclude Flutter iOS generated files.

Sequence Diagram(s)

sequenceDiagram
    participant UI as SpeechToTextScreen /<br/>TextToSpeechScreen
    participant ViewModel as STT/TTS ViewModel
    participant SDK as RunAnywhereSDK
    participant Service as ONNXCoreService
    participant JNI as RunAnywhereBridge
    participant Native as ONNX Native<br/>Backend

    UI->>ViewModel: loadModel(name, id)
    ViewModel->>SDK: loadSTTModel() / loadTTSModel()
    SDK->>Service: loadSTTModel(path) / loadTTSModel(path)
    Service->>Service: ensureInitialized()
    Service->>JNI: nativeSTTLoadModel(...)<br/>nativeTTSLoadModel(...)
    JNI->>Native: Call via JNI
    Native-->>JNI: Status code
    JNI-->>Service: Result
    Service->>Service: Update model state
    Service-->>SDK: Success
    SDK-->>ViewModel: Return component
    ViewModel->>ViewModel: Update isModelLoaded state
    ViewModel-->>UI: Emit state update
    UI->>UI: Show ready UI

    alt STT Flow
        UI->>ViewModel: toggleRecording()
        ViewModel->>Service: transcribe(audioSamples)
        Service->>JNI: nativeSTTTranscribe(...)
        JNI->>Native: Transcribe
        Native-->>JNI: Transcription text
        JNI-->>Service: Text result
        Service-->>ViewModel: Transcription
        ViewModel-->>UI: Update transcription state
    else TTS Flow
        UI->>ViewModel: generateSpeech(text)
        ViewModel->>Service: synthesize(text, voice, speed, pitch)
        Service->>JNI: nativeTTSSynthesize(...)
        JNI->>Native: Synthesize
        Native-->>JNI: Audio samples
        JNI-->>Service: NativeTTSSynthesisResult
        Service-->>ViewModel: Audio data
        ViewModel-->>UI: Update playback state
    end
Loading
sequenceDiagram
    participant Screen as VoiceAssistantScreen
    participant ViewModel as VoiceAssistantViewModel
    participant STTComp as STTComponent
    participant LLMComp as LLMComponent
    participant TTSComp as TTSComponent

    Screen->>ViewModel: setSTTModel(framework, name, id)
    ViewModel->>ViewModel: Update sttLoadState → LOADING
    ViewModel->>STTComp: (Simulate load)
    ViewModel->>ViewModel: sttLoadState → LOADED
    Screen->>ViewModel: setLLMModel(...)
    ViewModel->>LLMComp: (Load)
    ViewModel->>ViewModel: llmLoadState → LOADED
    Screen->>ViewModel: setTTSModel(...)
    ViewModel->>TTSComp: (Load)
    ViewModel->>ViewModel: ttsLoadState → LOADED
    Screen->>Screen: Check allModelsReady (all LOADED)
    activate Screen
    Screen->>ViewModel: startSession()
    ViewModel->>ViewModel: isListening → true
    ViewModel-->>Screen: Emit ready UI
    Screen->>Screen: Show MainVoiceAssistantUI
    deactivate Screen
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Key areas requiring close attention:
    • ONNXCoreService and RunAnywhereBridge JNI integration — New native layer with thread-safe mutex guarding, external JNI function declarations, and error code mapping; requires understanding of JNI contracts and native interop patterns.
    • VoiceAssistantScreen and VoiceAssistantViewModel architecture — Substantial refactoring introduces model lifecycle state machine (NOT_LOADED/LOADING/LOADED/ERROR), two-phase setup flow, and new SelectedModel/VoiceUiState data classes; verify state transitions and allModelsReady/allModelsLoaded logic.
    • SettingsScreen and SettingsViewModel — Large new feature with multi-section UI (SDK Config, Generation, API, Storage, Logging, About) and corresponding state management including routing policy, API key, model deletion, and cache clearing; check ViewModel update methods and state persistence hooks.
    • STT/TTS Screen and ViewModel additions — New public composables (SpeechToTextScreen, TextToSpeechScreen) with supporting ViewModels (STTMode/RecordingState enums, TTSUiState); verify state-driven UI logic and model-loading flows.
    • New public SDK API surface — RunAnywhere.kt adds loadSTTModel, loadTTSModel, estimateTokenCount and corresponding properties; GenerationResult.kt introduces new models with computed properties (effectiveTokensPerSecond, isSuccessful); verify property implementations and defaults.
    • Navigation restructuring — AppNavigation.kt replaces Storage/Quiz tabs with STT/TTS; confirm NavigationRoute constants, composable mappings, and UI bar styling are consistent.

Possibly related issues

Possibly related PRs

Poem

🐰 A Swift bridge to ONNX calls,
STT and TTS echo through the halls,
Voices transcribed, then synthesized bright,
New models loaded—the SDK takes flight!
From Android screens to token counts so true,
The RunAnywhere dream expands anew. 🎙️✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.87% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive PR description covers major changes but is largely incomplete with minimal detail in main description section; only checklist and type-of-change are partially filled. Expand the main Description section with more specific details about changes, add screenshots for UI components, mark testing checkboxes (currently unchecked), and clarify ONNX backend integration specifics.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly describes the primary changes: adding TTS and STT Android UI/UX updates, which matches the main objectives of adding SpeechToTextScreen and TextToSpeechScreen components.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 463505f and 14ae81c.

📒 Files selected for processing (22)
  • .gitignore (1 hunks)
  • examples/android/RunAnywhereAI/app/build.gradle.kts (2 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt (10 hunks)
  • examples/android/RunAnywhereAI/settings.gradle.kts (1 hunks)
  • examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig (0 hunks)
  • examples/flutter/RunAnywhereAI/ios/Flutter/flutter_export_environment.sh (0 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/.gitignore (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/VERSION (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/scripts/download-native-libs.sh (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt (6 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt (1 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…UI components

- Implemented ConversationListSheet and ChatDetailsSheet in ChatScreen for improved conversation management.
- Updated ChatViewModel to support loading and managing conversations, including new conversation creation and deletion.
- Refactored StorageViewModel to manage stored model information and integrate with the UI for better user experience.
- Added error handling and loading states in StorageViewModel for improved data management.
- Removed unused Color.kt file to streamline the project structure.

This commit enhances the application's chat and storage capabilities, aligning with the overall architecture and improving user interaction.
@sanchitmonga22
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sanchitmonga22
Copy link
Contributor Author

@greptile review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig (1)

1-14: Generated.xcconfig is tracked in git and contains machine-specific paths that will break builds for other developers.

Verification confirms this is a critical issue:

  • The file is tracked in git (confirmed via git ls-files)
  • It is not gitignored (git check-ignore returned no match)
  • The .gitignore pattern only covers **/ios/Flutter/ephemeral/, missing Generated.xcconfig
  • The file contains hardcoded user paths (/Users/sanchitmonga/...)

Remove this file from the commit and add it to .gitignore:

# In examples/flutter/RunAnywhereAI/.gitignore or root .gitignore, add:
**/ios/Flutter/Generated.xcconfig

Then run: git rm --cached examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig

examples/flutter/RunAnywhereAI/ios/Flutter/flutter_export_environment.sh (1)

1-13: Auto-generated Flutter file with user-specific paths is committed to version control and should be removed.

Verification confirms this is a critical issue. The file flutter_export_environment.sh is currently tracked in git (and not gitignored), alongside Generated.xcconfig. Both contain machine-specific and build-specific paths that will differ across developers' environments, causing:

  • Build failures for developers with different path structures
  • Merge conflicts on every build regeneration
  • Violation of the file's own header directive

Both files must be removed from the commit and added to .gitignore with a pattern like **/ios/Flutter/flutter_export_environment.sh and **/ios/Flutter/Generated.xcconfig.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt (1)

358-363: onCleared coroutine may not complete.

The coroutine launched in onCleared() may be cancelled immediately since viewModelScope is cancelled when the ViewModel is cleared. Call stopSession() synchronously or use a non-cancellable context if cleanup must complete.

     override fun onCleared() {
         super.onCleared()
-        viewModelScope.launch {
-            stopSession()
-        }
+        // Cancel the pipeline job directly - stopSession's coroutine work
+        // won't complete reliably in onCleared
+        pipelineJob?.cancel()
+        pipelineJob = null
     }
🧹 Nitpick comments (30)
sdk/runanywhere-swift/ARCHITECTURE.md (1)

11-22: Specify language identifiers for all fenced code blocks.

Multiple code blocks lack language specifiers, triggering markdown linting warnings (MD040). Add appropriate language tags to help with syntax highlighting and linting compliance.

Apply this diff to add language specifiers:

-```
+```text
 ┌─────────────────────────────────────────────────────────────────┐
-```
+```text
 Sources/
-```
+```text
 Sources/CRunAnywhereONNX/
-module CRunAnywhereONNX {
+```modulemap
+module CRunAnywhereONNX {
-```
+```text
 ┌──────────────────────────────────────────────────────────────┐
-```
+```text
 ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐
-```
+```text
 runanywhere-core/

Also applies to: 26-49, 69-74, 77-83, 134-149, 394-402, 506-519

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechScreen.kt (2)

612-620: Remove no-op modifier chain.

The .then(if (isSystemTTS) Modifier else Modifier) on line 615 is a no-op since both branches return an empty Modifier. This appears to be leftover scaffolding.

                 modifier = Modifier
                     .width(140.dp)
-                    .height(50.dp)
-                    .then(if (isSystemTTS) Modifier else Modifier),
+                    .height(50.dp),

716-723: Consider extracting shared formatBytes utility.

This function duplicates formatBytes in SettingsScreen.kt (lines 670-677), but with differences: this version takes Int instead of Long and doesn't handle the < 1024 bytes or >= 1 GB cases. Consider extracting to a shared utility for consistency.

-private fun formatBytes(bytes: Int): String {
-    val kb = bytes / 1024.0
-    return if (kb < 1024) {
-        String.format("%.1f KB", kb)
-    } else {
-        String.format("%.1f MB", kb / 1024.0)
-    }
-}
+private fun formatBytes(bytes: Int): String = formatBytes(bytes.toLong())
+
+private fun formatBytes(bytes: Long): String {
+    return when {
+        bytes < 1024 -> "$bytes B"
+        bytes < 1024 * 1024 -> String.format("%.1f KB", bytes / 1024.0)
+        bytes < 1024 * 1024 * 1024 -> String.format("%.1f MB", bytes / (1024.0 * 1024.0))
+        else -> String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0))
+    }
+}
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt (1)

68-75: Consider removing empty coroutine launch.

The initialize() function launches an empty coroutine. Until the actual audio session configuration is implemented, consider simplifying to avoid unnecessary coroutine overhead.

     fun initialize() {
-        viewModelScope.launch {
-            // TODO: Configure audio session for playback
-            // iOS equivalent:
-            // try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
-            // try AVAudioSession.sharedInstance().setActive(true)
-        }
+        // TODO: Configure audio session for playback
+        // iOS equivalent:
+        // try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)
+        // try AVAudioSession.sharedInstance().setActive(true)
     }
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt (1)

104-122: Consider lazy derivation for convenience StateFlows.

Creating 6 derived StateFlows eagerly with SharingStarted.Eagerly consumes memory even if they're not observed. Since these are "backward compatibility" accessors, consider using SharingStarted.WhileSubscribed() or lazy initialization to reduce overhead.

     val sessionState: StateFlow<SessionState> = _uiState.map { it.sessionState }.stateIn(
-        viewModelScope, SharingStarted.Eagerly, SessionState.DISCONNECTED
+        viewModelScope, SharingStarted.WhileSubscribed(5000), SessionState.DISCONNECTED
     )

Apply similarly to other derived flows (isListening, error, currentTranscript, assistantResponse, audioLevel).

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt (2)

200-208: Redundant state update before refreshData().

The state update to remove the model and recalculate modelStorageSize is immediately overwritten by refreshData() which loads mock data. This creates a brief UI flicker. Consider either removing the redundant update or having refreshData() preserve the deletion.

     fun deleteModel(modelId: String) {
         viewModelScope.launch {
             try {
                 // TODO: Replace with actual SDK integration
                 // iOS equivalent: try await RunAnywhere.deleteStoredModel(modelId)

-                _uiState.update { state ->
-                    state.copy(
-                        storedModels = state.storedModels.filter { it.id != modelId },
-                        modelStorageSize = state.storedModels
-                            .filter { it.id != modelId }
-                            .sumOf { it.size }
-                    )
-                }
-                refreshData()
+                // TODO: When SDK is integrated, call delete then refresh
+                // For now, just update the local state (mock behavior)
+                _uiState.update { state ->
+                    val updatedModels = state.storedModels.filter { it.id != modelId }
+                    state.copy(
+                        storedModels = updatedModels,
+                        modelStorageSize = updatedModels.sumOf { it.size },
+                        totalStorageSize = updatedModels.sumOf { it.size } + 50_000_000L
+                    )
+                }
             } catch (e: Exception) {

18-28: Consider consolidating StoredModelInfo with SettingsViewModel.

Per the AI summary, StoredModelInfo is duplicated in both StorageViewModel.kt and SettingsViewModel.kt. Consider extracting to a shared models file to avoid drift between implementations.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt (1)

65-73: Consider platform-specific icon mapping for Android.

The icon property uses SF Symbol names (waveform.badge.mic, waveform) which are iOS-specific. Android doesn't have these icons natively. Consider adding platform-specific icon resolution or using a cross-platform icon abstraction.

     /**
      * Icon identifier for the mode (matches iOS icon)
-     * Uses SF Symbol names for cross-platform icon lookup
+     * Uses SF Symbol names - Android consumers should map to Material icons
+     * (e.g., "waveform.badge.mic" → R.drawable.ic_mic, "waveform" → R.drawable.ic_waveform)
      */
     val icon: String
         get() = when (this) {
             BATCH -> "waveform.badge.mic"
             LIVE -> "waveform"
         }
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt (1)

30-37: Consider adding validation for probability range.

The probability field should logically be constrained to [0.0, 1.0]. Other result types in the codebase (e.g., WordTimestamp, TranscriptionAlternative in STTModels.kt) validate confidence ranges in their init blocks.

 data class VADResult(
     val isSpeech: Boolean,
     val probability: Float
-)
+) {
+    init {
+        require(probability in 0.0f..1.0f) { "Probability must be between 0.0 and 1.0" }
+    }
+}
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatScreen.kt (1)

1164-1164: Consider using thread-safe date formatting.

SimpleDateFormat is not thread-safe. While remember provides instance stability, consider using DateTimeFormatter (API 26+) or the format at call-site for safer recomposition:

// Option 1: Format inline without caching the formatter
val formattedDate = remember(conversation.updatedAt) {
    SimpleDateFormat("MMM d", Locale.getDefault()).format(Date(conversation.updatedAt))
}
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt (4)

89-93: Use explicit locale for consistent number formatting.

String.format without an explicit Locale can produce inconsistent decimal separators across devices (e.g., . vs ,). For UI display, consider using Locale.US or Locale.ROOT for consistency.

-                    Text(
-                        text = String.format("%.2f", uiState.temperature),
+                    Text(
+                        text = String.format(java.util.Locale.US, "%.2f", uiState.temperature),

440-440: Replace deprecated values() with entries.

Enum.values() is deprecated in Kotlin 1.9+. Use entries for better performance and type safety.

-            RoutingPolicy.values().forEach { policy ->
+            RoutingPolicy.entries.forEach { policy ->

670-678: Use explicit locale in formatBytes for consistent formatting.

Static analysis flagged implicit default locale usage. For byte formatting shown in UI, use an explicit locale.

 private fun formatBytes(bytes: Long): String {
     return when {
         bytes < 1024 -> "$bytes B"
-        bytes < 1024 * 1024 -> String.format("%.1f KB", bytes / 1024.0)
-        bytes < 1024 * 1024 * 1024 -> String.format("%.1f MB", bytes / (1024.0 * 1024.0))
-        else -> String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0))
+        bytes < 1024 * 1024 -> String.format(java.util.Locale.US, "%.1f KB", bytes / 1024.0)
+        bytes < 1024 * 1024 * 1024 -> String.format(java.util.Locale.US, "%.1f MB", bytes / (1024.0 * 1024.0))
+        else -> String.format(java.util.Locale.US, "%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0))
     }
 }

313-316: TODO: Implement documentation link.

This TODO should be tracked. Consider opening an issue or using Android's Intent.ACTION_VIEW with a URI to open the documentation URL.

Would you like me to generate the implementation for opening the documentation URL, or should I open an issue to track this?

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts (1)

128-138: Silent failure when ONNX distribution directory is missing.

If dist/android/onnx doesn't exist, the build proceeds silently without native libraries, leading to runtime failures. Consider logging a warning or failing the build if required libraries are absent.

     sourceSets {
         getByName("main") {
             val runAnywhereCoreDir = rootProject.projectDir.resolve("../../../runanywhere-core")
             val distDir = runAnywhereCoreDir.resolve("dist/android/onnx")

             if (distDir.exists()) {
                 jniLibs.srcDirs(distDir)
+            } else {
+                logger.warn("ONNX native libraries not found at: $distDir. Build may fail at runtime.")
             }
         }
     }
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt (3)

796-831: Consider extracting ModelBadge to a shared component.

This ModelBadge differs from ChatScreen.kt's ModelBadge (lines 560-605 in relevant snippets). Having two different implementations with the same name can cause confusion. Consider either:

  1. Extracting a shared ModelBadge component to a common location
  2. Renaming this one to VoiceModelBadge to distinguish it

82-86: Empty callback with unclear purpose.

The onStartVoice callback is empty with a comment saying the view auto-switches. If this callback isn't needed, consider removing the parameter from VoicePipelineSetupView to avoid confusion.

             VoicePipelineSetupView(
                 ...
                 onSelectTTS = { showTTSModelSelection = true },
-                onStartVoice = {
-                    // All models loaded, nothing to do here
-                    // The view will automatically switch to main voice UI
-                }
+                onStartVoice = { /* View auto-switches when models are loaded */ }
             )

Or remove the onStartVoice parameter entirely if it's never used meaningfully.


948-1016: MockModelSelectionDialog should be replaced before release.

The TODO indicates this is a temporary mock. Ensure this is tracked for replacement with the actual ModelSelectionSheet before the feature ships.

Would you like me to open an issue to track replacing the mock model selection dialogs with the actual SDK-integrated implementation?

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt (3)

329-331: Replace deprecated values() with entries.

Enum.values() is deprecated in Kotlin 1.9+. Use entries instead.

-            STTMode.values().forEach { mode ->
+            STTMode.entries.forEach { mode ->

3-3: Unused import.

animateContentSize is imported but not used in this file.

-import androidx.compose.animation.animateContentSize

161-216: Mock model picker should be tracked for replacement.

Similar to the VoiceAssistantScreen, this uses a temporary mock dialog. The TODO at line 162 indicates SDK integration is pending.

Would you like me to open an issue to track replacing the mock STT model picker with the actual ModelSelectionSheet implementation?

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/Capability.kt (1)

15-17: Inconsistent nullability across fromValue methods.

Capability.fromValue returns Capability? (nullable), while DeviceType.fromValue and ResultCode.fromValue return non-nullable defaults. This inconsistency could surprise callers expecting uniform behavior.

Consider aligning the return types—either all nullable with explicit handling, or all with a sensible default/unknown variant.

Option A – Add an UNKNOWN entry and return it as a default:

 enum class Capability(val value: Int) {
     TEXT_GENERATION(0),
     EMBEDDINGS(1),
     STT(2),
     TTS(3),
     VAD(4),
-    DIARIZATION(5);
+    DIARIZATION(5),
+    UNKNOWN(-1);

     companion object {
-        fun fromValue(value: Int): Capability? = entries.find { it.value == value }
+        fun fromValue(value: Int): Capability = entries.find { it.value == value } ?: UNKNOWN
     }
 }
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt (1)

73-80: Remove empty coroutine launch.

The viewModelScope.launch block contains only a comment. Remove the unnecessary coroutine until actual initialization logic is added.

     fun initialize() {
-        viewModelScope.launch {
-            // TODO: Configure audio session for recording
-            // iOS equivalent:
-            // try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
-            // try AVAudioSession.sharedInstance().setActive(true)
-        }
+        // TODO: Configure audio session for recording
+        // iOS equivalent:
+        // try AVAudioSession.sharedInstance().setCategory(.playAndRecord, mode: .default)
+        // try AVAudioSession.sharedInstance().setActive(true)
     }
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt (2)

227-240: Unnecessary coroutine launch.

updateApiKey launches a coroutine but only performs synchronous state updates. Either remove the launch for consistency with other update methods, or make it suspend if async storage is planned.

     fun updateApiKey(apiKey: String) {
-        viewModelScope.launch {
-            // TODO: Save to encrypted storage
-            // Android: EncryptedSharedPreferences
-            // iOS: KeychainService
-
-            _uiState.update {
-                it.copy(
-                    apiKey = apiKey,
-                    isApiKeyConfigured = apiKey.isNotEmpty()
-                )
-            }
+        // TODO: Save to encrypted storage
+        // Android: EncryptedSharedPreferences
+        // iOS: KeychainService
+
+        _uiState.update {
+            it.copy(
+                apiKey = apiKey,
+                isApiKeyConfigured = apiKey.isNotEmpty()
+            )
         }
+        saveConfiguration()
     }

324-335: Replace println with proper logging.

For Android, use android.util.Log or a logging library like Timber instead of println.

-            println("Configuration saved - Temperature: ${state.temperature}, MaxTokens: ${state.maxTokens}")
+            android.util.Log.d("SettingsViewModel", "Configuration saved - Temperature: ${state.temperature}, MaxTokens: ${state.maxTokens}")
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt (1)

3-4: Remove unused imports.

Dispatchers and withContext are imported but not used in this expect declaration file. The actual implementation will need them.

 package com.runanywhere.sdk.core.bridge
 
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-
 /**
  * ONNXCoreService - High-level service wrapper for RunAnywhere Core ONNX backend.
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt (2)

206-213: Inconsistent initialization check in getVoices().

Unlike other methods that call ensureInitialized() and throw when the backend isn't ready, getVoices() silently returns "[]". This inconsistency could mask initialization bugs.

Consider aligning with other methods:

     actual suspend fun getVoices(): String {
         return withContext(Dispatchers.IO) {
             mutex.withLock {
-                if (backendHandle == 0L) return@withContext "[]"
+                ensureInitialized()
                 RunAnywhereBridge.nativeTTSGetVoices(backendHandle)
             }
         }
     }

335-361: Companion utility functions perform blocking JNI calls on the calling thread.

getAvailableBackends(), getVersion(), and extractArchive() execute native calls synchronously. On Android, if called from the main thread, these could cause ANR. Consider making them suspend functions dispatched to Dispatchers.IO for consistency with the instance methods.

-        fun getAvailableBackends(): List<String> {
+        suspend fun getAvailableBackends(): List<String> = withContext(Dispatchers.IO) {
             RunAnywhereBridge.loadLibrary()
-            return RunAnywhereBridge.nativeGetAvailableBackends().toList()
+            RunAnywhereBridge.nativeGetAvailableBackends().toList()
         }
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt (1)

169-206: Scaffold implementation with extensive TODOs.

The transcription control methods contain substantial placeholder logic. While the state transitions are implemented, the actual audio capture and pipeline integration remain stubbed. This is acceptable for a draft PR, but ensure these TODOs are tracked.

Would you like me to open an issue to track the completion of the audio pipeline integration, including:

  • Microphone permission handling
  • ModularPipelineConfig integration
  • Audio capture stream processing
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt (1)

28-49: Swallowed exceptions should log for debugging.

The catch blocks at lines 35 and 41 intentionally swallow UnsatisfiedLinkError for optional/pre-loaded dependencies, but silent failures can make debugging difficult. Consider adding debug logging.

             try {
                 System.loadLibrary("runanywhere_bridge")
             } catch (e: UnsatisfiedLinkError) {
                 // May already be loaded or linked statically
+                // Log at debug level for troubleshooting
+                android.util.Log.d("RunAnywhereBridge", "runanywhere_bridge not loaded separately: ${e.message}")
             }

             try {
                 System.loadLibrary("onnxruntime")
             } catch (e: UnsatisfiedLinkError) {
                 // May already be loaded
+                android.util.Log.d("RunAnywhereBridge", "onnxruntime not loaded separately: ${e.message}")
             }

Note: Since this is in jvmAndroidMain, you may want to use a platform-agnostic logging approach or println for JVM compatibility.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd4c4ae and 463505f.

📒 Files selected for processing (29)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/MainActivity.kt (0 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatScreen.kt (4 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatViewModel.kt (0 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/navigation/AppNavigation.kt (6 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechScreen.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionScreen.kt (5 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt (1 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt (11 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt (3 hunks)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/ui/theme/Color.kt (0 hunks)
  • examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig (1 hunks)
  • examples/flutter/RunAnywhereAI/ios/Flutter/flutter_export_environment.sh (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/proguard-rules.pro (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/Capability.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt (1 hunks)
  • sdk/runanywhere-kotlin/settings.gradle.kts (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt (1 hunks)
  • sdk/runanywhere-swift/ARCHITECTURE.md (1 hunks)
💤 Files with no reviewable changes (3)
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/MainActivity.kt
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatViewModel.kt
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/ui/theme/Color.kt
🧰 Additional context used
📓 Path-based instructions (3)
sdk/runanywhere-kotlin/**/src/**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

sdk/runanywhere-kotlin/**/src/**/*.kt: All business logic, protocols, interfaces, and structures MUST be defined in commonMain/ for Kotlin Multiplatform projects. Platform-specific implementations must use clear prefixes like AndroidTTSService.kt, JvmTTSService.kt, etc.
NEVER make assumptions when implementing KMP code. ALWAYS refer to the iOS implementation as the definitive source of truth. Check the iOS implementation, copy the logic exactly, and adapt only for Kotlin syntax.
Use expect/actual ONLY for platform-specific implementations, not for business logic. Put all business logic in commonMain/.
Use Flow instead of AsyncSequence for reactive streams in Kotlin Multiplatform code.
Use coroutines and suspend functions instead of async/await patterns for asynchronous operations.
Use sealed classes for type-safe error handling in Kotlin code.
Always use data classes and structured types (enums, sealed classes) instead of strings for models and configuration.
Use the ModuleRegistry provider pattern for extensibility and plugin architecture instead of hard-coded dependencies.
Use EventBus for component communication instead of direct coupling between components.
Use Service Container pattern for centralized dependency injection with lazy initialization.
Use lazy initialization for service dependencies to avoid memory pressure and allow garbage collection.

Files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/Capability.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt
sdk/runanywhere-kotlin/**/src/**/components/**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

Implement proper component lifecycle management with initialization, state tracking, and cleanup in BaseComponent.

Files:

  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt
sdk/runanywhere-kotlin/**/*.gradle.kts

📄 CodeRabbit inference engine (CLAUDE.md)

sdk/runanywhere-kotlin/**/*.gradle.kts: Kotlin version must be 2.1.21 or later for the Kotlin Multiplatform SDK.
JVM target must be 17 or later for Kotlin Multiplatform SDK.
Android minSdk must be 24 or later for Kotlin Multiplatform SDK.

Files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/androidMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use coroutines and suspend functions instead of async/await patterns for asynchronous operations.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use the `ModuleRegistry` provider pattern for extensibility and plugin architecture instead of hard-coded dependencies.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/components/**/*.kt : Implement proper component lifecycle management with initialization, state tracking, and cleanup in BaseComponent.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/jvmMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use sealed classes for type-safe error handling in Kotlin code.

Applied to files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/Capability.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : All business logic, protocols, interfaces, and structures MUST be defined in `commonMain/` for Kotlin Multiplatform projects. Platform-specific implementations must use clear prefixes like `AndroidTTSService.kt`, `JvmTTSService.kt`, etc.

Applied to files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/components/**/*.kt : Implement proper component lifecycle management with initialization, state tracking, and cleanup in BaseComponent.

Applied to files:

  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use the `ModuleRegistry` provider pattern for extensibility and plugin architecture instead of hard-coded dependencies.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/androidMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/proguard-rules.pro
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/jvmMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/proguard-rules.pro
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : Android minSdk must be 24 or later for Kotlin Multiplatform SDK.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : Kotlin version must be 2.1.21 or later for the Kotlin Multiplatform SDK.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : JVM target must be 17 or later for Kotlin Multiplatform SDK.

Applied to files:

  • sdk/runanywhere-kotlin/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
📚 Learning: 2025-10-17T22:19:36.568Z
Learnt from: shubhammalhotra28
Repo: RunanywhereAI/runanywhere-sdks PR: 119
File: README.md:176-176
Timestamp: 2025-10-17T22:19:36.568Z
Learning: The RunAnywhere SDK package repository is located at `https://github.com/RunanywhereAI/runanywhere-sdks`. The repository was moved from `sdks` to `runanywhere-sdks`, so the correct URL to reference in documentation and installation instructions is `https://github.com/RunanywhereAI/runanywhere-sdks`.

Applied to files:

  • sdk/runanywhere-swift/ARCHITECTURE.md
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.

Applied to files:

  • sdk/runanywhere-swift/ARCHITECTURE.md
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use Service Container pattern for centralized dependency injection with lazy initialization.

Applied to files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use `expect/actual` ONLY for platform-specific implementations, not for business logic. Put all business logic in `commonMain/`.

Applied to files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Always use data classes and structured types (enums, sealed classes) instead of strings for models and configuration.

Applied to files:

  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt
  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use lazy initialization for service dependencies to avoid memory pressure and allow garbage collection.

Applied to files:

  • examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
📚 Learning: 2025-11-26T22:49:40.343Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.343Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use coroutines and suspend functions instead of async/await patterns for asynchronous operations.

Applied to files:

  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreServiceImpl.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
🧬 Code graph analysis (3)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechScreen.kt (1)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt (1)
  • formatBytes (671-678)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt (1)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt (1)
  • subscribeToModelLifecycle (139-149)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt (1)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatScreen.kt (1)
  • ModelBadge (561-606)
🪛 detekt (1.23.8)
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt

[warning] 90-90: String.format("%.2f", uiState.temperature) uses implicitly default locale for string formatting.

(detekt.potential-bugs.ImplicitDefaultLocale)


[warning] 674-674: String.format("%.1f KB", bytes / 1024.0) uses implicitly default locale for string formatting.

(detekt.potential-bugs.ImplicitDefaultLocale)


[warning] 675-675: String.format("%.1f MB", bytes / (1024.0 * 1024.0)) uses implicitly default locale for string formatting.

(detekt.potential-bugs.ImplicitDefaultLocale)


[warning] 676-676: String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0)) uses implicitly default locale for string formatting.

(detekt.potential-bugs.ImplicitDefaultLocale)

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt

[warning] 35-35: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 41-41: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🪛 markdownlint-cli2 (0.18.1)
sdk/runanywhere-swift/ARCHITECTURE.md

11-11: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


26-26: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


69-69: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


134-134: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


394-394: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


506-506: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (swift)
🔇 Additional comments (43)
sdk/runanywhere-swift/ARCHITECTURE.md (2)

87-124: Swift code examples are well-structured and aligned with SDK architecture.

The usage patterns shown for consuming the C API via CRunAnywhereONNX module and the async/await handling match best practices outlined in the learnings for Kotlin (coroutines/suspend functions carry over conceptually to Swift concurrency).


167-185: ModuleRegistry pattern aligns with learnings on plugin architecture.

The provider registry implementation for STT/TTS/VAD/LLM backends matches the ModuleRegistry pattern referenced in learnings for extensibility and pluggable architecture. Priority-based provider selection is a clean design choice.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechScreen.kt (1)

40-46: Good lifecycle-aware state collection.

Using collectAsStateWithLifecycle ensures proper lifecycle handling and prevents unnecessary recompositions when the screen is not visible.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt (1)

53-59: Well-structured ViewModel with proper state management.

Good use of MutableStateFlow with asStateFlow() for encapsulation, and proper cleanup in onCleared(). The playback job management pattern is appropriate for managing the simulated playback lifecycle.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt (1)

17-25: Good use of enum with computed properties.

ModelLoadState enum with isLoaded and isLoading computed properties provides a clean API for state checking without exposing implementation details.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/storage/StorageViewModel.kt (1)

56-65: Well-structured ViewModel following data class guidelines.

Good use of data classes (StoredModelInfo, StorageUiState) for structured types as per coding guidelines. The StateFlow pattern and error handling are properly implemented.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt (1)

381-394: Perfect! I've completed the verification. Let me provide the rewritten review comment:


STTMode enum properly defined and accessible—implementation is solid.

The new supportsStreaming and recommendedMode properties provide a clean public API for querying service capabilities. The safe navigation with fallback defaults (?: false) ensures robustness when the service is not yet initialized.

Both STTComponent.kt and STTMode enum (defined in STTModels.kt) are in the same package (com.runanywhere.sdk.components.stt), so STTMode is automatically accessible without explicit imports. The enum includes all necessary utilities: BATCH and LIVE values, computed properties (displayName, description, icon), and a factory method (fromValue()).

sdk/runanywhere-kotlin/settings.gradle.kts (1)

44-47: LGTM!

The new module inclusion follows the same unconditional pattern as other core modules (whisperkit, llm-llamacpp, llm-mlc). The comments clearly document the module's purpose as an ONNX Runtime backend via JNI, analogous to Swift's CRunAnywhereONNX.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt (1)

75-81: LGTM!

The fromValue() factory method correctly uses entries.find() (Kotlin 1.9+) and returns a nullable type for graceful handling of unknown values.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt (2)

39-45: LGTM - design is appropriate for bridge-level exceptions.

While coding guidelines recommend sealed classes for error handling, this exception wraps ResultCode which provides type-safe error categorization. A sealed hierarchy would add complexity without benefit at the JNI bridge layer.


7-28: LGTM!

Correctly implements equals() and hashCode() using contentEquals() and contentHashCode() for the FloatArray field - essential for proper data class behavior with array types.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionScreen.kt (3)

26-30: LGTM - improved naming consistency.

The state variable renaming (isRecordingisTranscribing, errorerrorMessage) better reflects the actual UI state semantics and aligns with the ViewModel API.


74-99: LGTM!

Recording controls correctly use the updated ViewModel methods (startTranscription/stopTranscription/clearTranscripts) and properly toggle based on isTranscribing state.


182-211: LGTM!

Error display correctly handles the nullable errorMessage state and provides a dismiss action via clearError().

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/chat/ChatScreen.kt (4)

262-284: LGTM - Sheet integration follows iOS patterns.

The conversation list sheet correctly integrates with ConversationStore via LocalContext, handles selection/creation/deletion callbacks, and properly dismisses on interaction completion.


1027-1036: LGTM!

Search filtering correctly uses case-insensitive matching on both conversation title and message content, with proper null-safety for the optional title.


1320-1365: LGTM - Analytics calculations are defensive.

The performance summary correctly handles edge cases: takeIf { !it.isNaN() } guards against empty list averages, and sumOf safely returns 0 for empty collections.


1438-1520: LGTM!

MessageAnalyticsCard provides a clean, information-dense display of per-message analytics with proper formatting and conditional thinking mode indicator.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsScreen.kt (1)

646-651: Clarify or verify the "stored securely" claim.

The text states "Your API key is stored securely," but this depends on the ViewModel's implementation. Ensure the API key is actually stored using Android's EncryptedSharedPreferences or Keystore. If not yet implemented, consider rewording to avoid misleading users.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/proguard-rules.pro (1)

1-35: LGTM!

The ProGuard rules appropriately preserve JNI-related classes, native methods, and the public API surface. Keeping all members for JNI bridge classes and result types is correct since JNI accesses fields by name/reflection.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt (1)

44-218: Overall implementation looks good.

The STT screen follows the iOS reference pattern well, with clear separation of concerns between the main screen, status banner, mode selector, recording button, and transcription display. The UI states are handled appropriately.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts (2)

68-73: Build configuration fully complies with all SDK requirements.

Verification confirms:

  • Kotlin version: 2.1.21 ✓ (from libs.versions.toml, meets requirement of 2.1.21 or later)
  • JVM target: 17 ✓ (lines 23, 29, 114-115 in build.gradle.kts)
  • Android minSdk: 24 ✓ (line 73 in build.gradle.kts)

The build configuration meets all Kotlin Multiplatform SDK guidelines.


36-38: The suggested fix is incorrect and would break the build.

The project path :runanywhere-kotlin does not exist in settings.gradle.kts. The root project is registered as "RunAnywhereKotlinSDK", and modules are included as :modules:runanywhere-core-onnx, not :runanywhere-kotlin.

The current pattern api(project.parent!!.parent!!) is correct and follows standard Gradle multiproject conventions. The structure (module → modules directory → root) is guaranteed by settings.gradle.kts, making the !! operator appropriate. This pattern is consistently used across other modules (runanywhere-llm-llamacpp, runanywhere-llm-mlc), and an alternative pattern api(project(":")) is used in runanywhere-whisperkit, both achieving the same result.

No changes are needed.

Likely an incorrect or invalid review comment.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/Capability.kt (2)

24-38: LGTM!

The DeviceType enum correctly maps to native values with a sensible CPU default for unrecognized values.


44-63: LGTM!

Good design with negative error codes, the isSuccess convenience property, and a safe default to ERROR_UNKNOWN for unrecognized values.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt (7)

25-29: LGTM!

Clear state enum for the recording state machine.


35-46: LGTM!

Well-structured data class with sensible defaults for all fields.


98-135: LGTM!

Good state management pattern with proper error handling. The mock implementation is clearly marked with TODOs for future SDK integration.


143-151: LGTM!

Correct state machine pattern for toggling recording. The empty PROCESSING branch appropriately prevents state changes during processing.


159-179: LGTM!

Clear state transitions with appropriate placeholders for future audio capture integration.


187-223: LGTM!

Proper state management with error handling that correctly resets to IDLE state on failure.


230-263: LGTM!

Clean implementation of helper methods with consistent state update patterns.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/navigation/AppNavigation.kt (3)

36-72: LGTM!

Clean Scaffold-based navigation with proper NavHost configuration. The 5-tab structure aligns with the iOS reference.


170-186: LGTM!

Clean route constants and data class for navigation items.


84-163: AppColors.primaryBlue is properly defined and available for use.

The primaryBlue color constant (value 0xFF007AFF) is correctly defined in AppColors.kt at line 16 and properly imported in the AppNavigation.kt file. The implementation follows consistent patterns across the codebase.

examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt (3)

16-21: LGTM!

Good use of enum with both display name and raw value for serialization, following coding guidelines for structured types.


27-69: LGTM!

Well-structured data classes with appropriate types and defaults. Good separation of concerns between model metadata and UI state.


91-185: LGTM!

Good initialization pattern with proper loading state management in loadStorageData(). The mock implementations are clearly marked for future SDK integration.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt (1)

27-235: LGTM!

Excellent API design following KMP best practices:

  • expect class in commonMain with platform-specific actual implementations
  • Consistent use of suspend functions for async operations (per coding guidelines)
  • Structured return types (TTSSynthesisResult, VADResult) instead of raw primitives
  • Clear capability groupings (STT, TTS, VAD, Embedding)
  • Comprehensive KDoc with usage example
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt (2)

25-44: Well-structured data classes with serialization support.

Good use of @Serializable data classes matching the iOS structure. The default values for id and timestamp provide sensible defaults while keeping the classes flexible.


91-94: ModelLoadState is properly accessible without an explicit import.

Both TranscriptionViewModel.kt and VoiceAssistantViewModel.kt are in the same package (com.runanywhere.runanywhereai.presentation.voice). In Kotlin, symbols defined in the same package are automatically accessible, so no import statement is required. The code at lines 91-94 will compile without issues.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/bridge/RunAnywhereBridge.kt (2)

56-125: Well-organized JNI bindings with comprehensive documentation.

The backend lifecycle bindings are well-documented with clear parameter descriptions and return value semantics. The use of @JvmStatic is correct for JNI external functions.


191-226: STT streaming API bindings look complete.

The streaming STT API (nativeSTTCreateStream, nativeSTTFeedAudio, nativeSTTDecode, etc.) provides a comprehensive interface for real-time transcription. The documentation note about destroying stream handles on the creation thread is important—consider adding this to the individual method KDoc as well.

Comment on lines 73 to 78
ModelStatusBannerSTT(
framework = uiState.selectedFramework,
modelName = uiState.selectedModelName,
isLoading = uiState.recordingState == RecordingState.PROCESSING && uiState.selectedModelName == null,
onSelectModel = { showModelPicker = true }
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unusual loading state condition.

The isLoading condition checks recordingState == RecordingState.PROCESSING && selectedModelName == null. This seems contradictory—how can processing occur without a model loaded? This may cause the loading indicator to never display as intended.

Consider revising the condition. If you want to show loading during model initialization:

             ModelStatusBannerSTT(
                 framework = uiState.selectedFramework,
                 modelName = uiState.selectedModelName,
-                isLoading = uiState.recordingState == RecordingState.PROCESSING && uiState.selectedModelName == null,
+                isLoading = uiState.isModelLoading,  // Add a dedicated loading state to ViewModel
                 onSelectModel = { showModelPicker = true }
             )

Or clarify the intended behavior if this condition is correct.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt
around lines 73 to 78, the isLoading condition uses && which only shows loading
when processing and no model is selected (contradictory); change the condition
to use || so the banner shows when either processing is happening or when no
model is selected (i.e., isLoading = recordingState == RecordingState.PROCESSING
|| selectedModelName == null) to reflect intended loading behavior during model
initialization or processing.

Comment on lines +16 to +19
enum class STTMode {
BATCH, // Record full audio then transcribe
LIVE // Real-time streaming transcription
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for all STTMode enum definitions
rg -n "enum class STTMode" --type=kotlin

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 354


🏁 Script executed:

#!/bin/bash
# Also search for STTMode references more broadly
rg -n "STTMode" --type=kotlin -C2

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 22038


🏁 Script executed:

#!/bin/bash
# Find STTModels.kt file mentioned in the AI summary
fd "STTModels.kt" --type f

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 166


🏁 Script executed:

#!/bin/bash
# Read the SpeechToTextViewModel.kt file to see imports and full definition
cat -n "examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt" 2>/dev/null || echo "File not found, searching for it..."

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 10122


🏁 Script executed:

#!/bin/bash
# Search for the file if the direct path doesn't work
fd "SpeechToTextViewModel.kt" --type f

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 194


🏁 Script executed:

#!/bin/bash
# Read SDK's STTModels.kt to see full definition
cat -n "sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt" | head -90

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 2957


🏁 Script executed:

#!/bin/bash
# Check package structure and exports in SDK
grep -n "^package\|^import\|^object\|^public" "sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt" | head -20

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 363


🏁 Script executed:

#!/bin/bash
# Check if app has any dependency on SDK in build files
fd "build.gradle\|build.gradle.kts" "examples/android" --type f | xargs grep -l "runanywhere" 2>/dev/null | head -3

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 56


🏁 Script executed:

#!/bin/bash
# Find and read app's build.gradle or build.gradle.kts
find examples/android -name "build.gradle.kts" -o -name "build.gradle" | head -5

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 173


🏁 Script executed:

#!/bin/bash
# Check the main app build file
cat examples/android/RunAnywhereAI/app/build.gradle.kts 2>/dev/null || cat examples/android/RunAnywhereAI/app/build.gradle 2>/dev/null | head -80

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 10405


🏁 Script executed:

#!/bin/bash
# Check if there's a settings.gradle that includes SDK modules
find examples/android -name "settings.gradle*" -exec cat {} \;

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 1441


Import STTMode from the SDK instead of redefining it locally.

The app already has sdk:runanywhere-kotlin as a dependency (build.gradle.kts line: implementation(project(":sdk:runanywhere-kotlin"))). The SDK's STTMode enum in STTModels.kt is richer—it includes serialization (value property), UI properties (displayName, description, icon), and a fromValue() companion function. Redefining it locally loses these features and creates maintenance burden.

Replace the local enum definition with an import:

import com.runanywhere.sdk.components.stt.STTMode

Remove lines 12-19 from SpeechToTextViewModel.kt and update SpeechToTextScreen.kt to use the SDK's STTMode.

🤖 Prompt for AI Agents
In
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt
around lines 16 to 19, the local STTMode enum is redefined; remove lines 12-19
to eliminate the duplicate definition, add an import for the SDK enum
(com.runanywhere.sdk.components.stt.STTMode) at the top of the file, and update
any usages in SpeechToTextViewModel and SpeechToTextScreen to reference the
SDK's STTMode (including using its value/displayName/description/icon or
fromValue() where appropriate) so the app uses the richer, serialized SDK type.

Comment on lines +112 to 117
// Initialize SDK
RunAnywhere.initialize(
apiKey = "demo-api-key",
baseURL = "https://api.runanywhere.ai",
environment = com.runanywhere.sdk.data.models.SDKEnvironment.DEVELOPMENT
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Hardcoded API key should be externalized.

The hardcoded "demo-api-key" is acceptable for development, but ensure this doesn't ship to production. Consider using BuildConfig fields or a secure configuration mechanism.

// Example: Use BuildConfig for API key
RunAnywhere.initialize(
    apiKey = BuildConfig.RUNANYWHERE_API_KEY,
    baseURL = BuildConfig.RUNANYWHERE_BASE_URL,
    environment = ...
)
🤖 Prompt for AI Agents
In
examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt
around lines 112-117, the API key is hardcoded ("demo-api-key"); replace it with
a configurable BuildConfig field (or other secure config) and update
app/build.gradle to define RUNANYWHERE_API_KEY and RUNANYWHERE_BASE_URL as
buildConfigField values for debug/release variants, then reference
BuildConfig.RUNANYWHERE_API_KEY and BuildConfig.RUNANYWHERE_BASE_URL in the
RunAnywhere.initialize call and ensure real production keys are injected via
CI/secrets and not committed to source control.

Comment on lines 63 to 95
actual val isInitialized: Boolean
get() = backendHandle != 0L && RunAnywhereBridge.nativeIsInitialized(backendHandle)

actual val supportedCapabilities: List<Capability>
get() {
if (backendHandle == 0L) return emptyList()
return RunAnywhereBridge.nativeGetCapabilities(backendHandle)
.mapNotNull { Capability.fromValue(it) }
}

actual fun supportsCapability(capability: Capability): Boolean {
if (backendHandle == 0L) return false
return RunAnywhereBridge.nativeSupportsCapability(backendHandle, capability.value)
}

actual val deviceType: DeviceType
get() {
if (backendHandle == 0L) return DeviceType.CPU
return DeviceType.fromValue(RunAnywhereBridge.nativeGetDevice(backendHandle))
}

actual val memoryUsage: Long
get() {
if (backendHandle == 0L) return 0
return RunAnywhereBridge.nativeGetMemoryUsage(backendHandle)
}

actual fun destroy() {
if (backendHandle != 0L) {
RunAnywhereBridge.nativeDestroy(backendHandle)
backendHandle = 0
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Race condition: property getters and destroy() access backendHandle without mutex protection.

The suspend functions correctly use mutex.withLock, but these property getters and destroy() read/write backendHandle without synchronization. This can lead to use-after-free if destroy() is called concurrently with another operation, or inconsistent reads during initialization.

Consider making destroy() a suspend function with mutex protection, and either:

  1. Mark the class as not thread-safe for property access, or
  2. Use @Volatile on backendHandle for visibility guarantees on reads, and protect destroy() with the mutex:
+    actual suspend fun destroy() {
+        withContext(Dispatchers.IO) {
+            mutex.withLock {
-    actual fun destroy() {
-        if (backendHandle != 0L) {
-            RunAnywhereBridge.nativeDestroy(backendHandle)
-            backendHandle = 0
-        }
+                if (backendHandle != 0L) {
+                    RunAnywhereBridge.nativeDestroy(backendHandle)
+                    backendHandle = 0
+                }
+            }
+        }
     }

For property getters, if the expect declaration requires non-suspend properties, document the thread-safety contract clearly or use @Volatile:

+    @Volatile
     private var backendHandle: Long = 0

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

29 files reviewed, 25 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 1 to 3
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/programming.com/flutter
FLUTTER_APPLICATION_PATH=/Users/programming.com/Downloads/runanywhere-sdks-main/examples/flutter/RunAnywhereAI
FLUTTER_ROOT=/Users/sanchitmonga/flutter
FLUTTER_APPLICATION_PATH=/Users/sanchitmonga/development/ODLM/runanywhere-all/sdks/examples/flutter/RunAnywhereAI
Copy link

Choose a reason for hiding this comment

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

logic: This auto-generated file contains developer-specific local paths and should not be committed to version control. The comment on line 1 explicitly states this. Add ios/Flutter/Generated.xcconfig to .gitignore and remove this file from the repository.

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig
Line: 1:3

Comment:
**logic:** This auto-generated file contains developer-specific local paths and should not be committed to version control. The comment on line 1 explicitly states this. Add `ios/Flutter/Generated.xcconfig` to .gitignore and remove this file from the repository.

How can I resolve this? If you propose a fix, please make it concise.

* Exception thrown when a RunAnywhere operation fails.
*/
class RunAnywhereException(
val resultCode: ResultCode,
Copy link

Choose a reason for hiding this comment

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

logic: ResultCode enum is referenced but not defined - this will cause compilation errors

Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/BridgeResults.kt
Line: 43:43

Comment:
**logic:** `ResultCode` enum is referenced but not defined - this will cause compilation errors

How can I resolve this? If you propose a fix, please make it concise.

@@ -1,14 +1,18 @@
package com.runanywhere.runanywhereai.presentation.navigation

import androidx.compose.foundation.background
Copy link

Choose a reason for hiding this comment

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

style: Import background is added but never used

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/navigation/AppNavigation.kt
Line: 3:3

Comment:
**style:** Import `background` is added but never used

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 278 to 281
modelStorageSize = state.downloadedModels
.filter { it.id != modelId }
.sumOf { it.size }
)
Copy link

Choose a reason for hiding this comment

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

logic: Bug in modelStorageSize calculation - uses original list instead of filtered list. Should use the filtered models for size calculation.

Suggested change
modelStorageSize = state.downloadedModels
.filter { it.id != modelId }
.sumOf { it.size }
)
modelStorageSize = state.downloadedModels
.filter { it.id != modelId }
.sumOf { it.size }
Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt
Line: 278:281

Comment:
**logic:** Bug in modelStorageSize calculation - uses original list instead of filtered list. Should use the filtered models for size calculation.

```suggestion
                    modelStorageSize = state.downloadedModels
                        .filter { it.id != modelId }
                        .sumOf { it.size }
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +204 to +207
val mockTranscription = when (_uiState.value.mode) {
STTMode.BATCH -> "This is a mock batch transcription. In production, this would be the actual transcribed text from the recorded audio using WhisperKit or ONNX Runtime models."
STTMode.LIVE -> "This is a mock live transcription. In production, this would show real-time streaming transcription results as you speak."
}
Copy link

Choose a reason for hiding this comment

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

style: mock transcription strings are very long and could be extracted to constants for better maintainability

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextViewModel.kt
Line: 204:207

Comment:
**style:** mock transcription strings are very long and could be extracted to constants for better maintainability

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

/**
* Get device type being used.
*/
val deviceType: DeviceType
Copy link

Choose a reason for hiding this comment

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

syntax: DeviceType is not defined - need to import or define this enum

Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
Line: 55:55

Comment:
**syntax:** `DeviceType` is not defined - need to import or define this enum

How can I resolve this? If you propose a fix, please make it concise.

voiceId: String? = null,
speedRate: Float = 1.0f,
pitchShift: Float = 0.0f
): TTSSynthesisResult
Copy link

Choose a reason for hiding this comment

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

syntax: TTSSynthesisResult is not defined - need to import or define this data class

Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
Line: 145:145

Comment:
**syntax:** `TTSSynthesisResult` is not defined - need to import or define this data class

How can I resolve this? If you propose a fix, please make it concise.

* @param sampleRate Sample rate
* @return VADResult with speech status and probability
*/
suspend fun processVAD(audioSamples: FloatArray, sampleRate: Int): VADResult
Copy link

Choose a reason for hiding this comment

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

syntax: VADResult is not defined - need to import or define this data class

Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/commonMain/kotlin/com/runanywhere/sdk/core/bridge/ONNXCoreService.kt
Line: 181:181

Comment:
**syntax:** `VADResult` is not defined - need to import or define this data class

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +292 to +297
while (true) {
delay(100)
// Simulate audio level changes
val randomLevel = (Math.random() * 0.5f).toFloat()
_uiState.update { it.copy(audioLevel = randomLevel) }
}
Copy link

Choose a reason for hiding this comment

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

logic: Infinite while loop without cancellation handling could cause resource leaks if coroutine scope cleanup fails.

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt
Line: 292:297

Comment:
**logic:** Infinite while loop without cancellation handling could cause resource leaks if coroutine scope cleanup fails.

How can I resolve this? If you propose a fix, please make it concise.

.background(MaterialTheme.colorScheme.surfaceVariant)
) {
Icon(
imageVector = if (showModelInfo) Icons.Default.Info else Icons.Default.Info,
Copy link

Choose a reason for hiding this comment

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

style: Icon vector condition uses same icon for both states

Suggested change
imageVector = if (showModelInfo) Icons.Default.Info else Icons.Default.Info,
imageVector = if (showModelInfo) Icons.Default.InfoOutlined else Icons.Default.Info,

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt
Line: 571:571

Comment:
**style:** Icon vector condition uses same icon for both states

```suggestion
                    imageVector = if (showModelInfo) Icons.Default.InfoOutlined else Icons.Default.Info,
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

sanchitmonga22 and others added 2 commits November 28, 2025 18:05
- Update build.gradle.kts to download pre-built native libs from GitHub releases
- Add download-native-libs.sh script for manual downloads
- Add VERSION file to track native library version
- Add .gitignore to exclude downloaded jniLibs
- Move generic bridge types to main SDK commonMain
- Refactor ONNX module to use downloaded libraries by default

Build modes:
- Remote (default): Downloads from GitHub releases
- Local: Uses locally built libs (-Prunanywhere.native.local=true)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Changed version from 0.0.1-dev to 0.0.1-dev.e2ac4eb to reflect the latest build metadata, ensuring accurate version tracking for the ONNX module.
@sanchitmonga22
Copy link
Contributor Author

@ellipsis review this pull request

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Caution

Changes requested ❌

Reviewed everything up to d608d01 in 4 minutes and 14 seconds. Click for details.
  • Reviewed 8807 lines of code in 34 files
  • Skipped 0 files when reviewing.
  • Skipped posting 18 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt:190
  • Draft comment:
    Mock delay (delay(2000)) is used to simulate TTS generation. Ensure you replace this with actual TTS synthesis integration before production.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment is asking the author to "Ensure you replace this with actual TTS synthesis integration before production." This violates the rule about not asking the PR author to confirm, ensure, or double-check things. The code already has a TODO comment on line 185 saying "TODO: Replace with actual SDK integration" and line 190 explicitly labels it as "Mock speech generation delay". The entire file is clearly a work-in-progress with mock implementations, as evidenced by the numerous TODO comments throughout. The comment doesn't provide any new information or actionable code change - it's just restating what's already obvious from the code itself. Could this comment be valuable for someone who might miss all the TODO comments? Perhaps it's highlighting a specific production readiness concern that needs tracking? Even if someone missed the TODO comments, this comment doesn't provide an actionable code change - it's just asking the author to "ensure" something is done later. The rules explicitly state not to make comments that ask the author to ensure, verify, or confirm things. The existing TODO comments already serve as reminders for what needs to be implemented. This comment should be deleted. It violates the rule against asking the author to "ensure" things, and it's redundant with the existing TODO comment on line 185 and the explicit "Mock speech generation delay" comment on line 190. It doesn't suggest any specific code change.
2. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionScreen.kt:133
  • Draft comment:
    Consider using a LazyColumn instead of a Box with verticalScroll for the transcript display to improve performance on long transcripts.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt:46
  • Draft comment:
    The VoiceAssistantScreen composable is quite lengthy. Consider refactoring it into smaller subcomponents to improve readability and maintainability.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantViewModel.kt:291
  • Draft comment:
    The infinite loop in startSession() (lines 291-297) may lead to resource issues if not properly cancelled. Ensure a robust cancellation mechanism is in place.
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
5. examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig:2
  • Draft comment:
    This auto-generated configuration file contains user-specific absolute paths. Consider parameterizing these paths or removing them to avoid committing developer-specific settings.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The file itself says "do not edit or check into version control" at line 1, which means this is an auto-generated file that shouldn't be committed at all. The comment is pointing out that user-specific paths are being committed, which is indeed happening in this PR. However, the real issue is that this entire file shouldn't be in version control in the first place. The comment is about changes that were made (the paths changed), so it is about the diff. But the comment is somewhat informative/advisory rather than actionable - it's asking the author to "consider" doing something. The rules state comments should not be purely informative and must clearly require a code change. This comment doesn't clearly state what action to take - should they gitignore the file? Should they revert the commit? It's vague. The comment does identify a real problem - user-specific paths are being committed to version control when the file itself says not to commit it. This could be considered actionable if the intent is to have the author add this file to .gitignore or revert the changes. The comment is about actual changes in the diff, not unchanged code. While the comment identifies a real issue, it uses weak language like "Consider" which makes it advisory rather than directive. The rules explicitly state comments should clearly require a code change, not be speculative or ask the author to consider things. The comment doesn't clearly state what action should be taken. Additionally, this is a generated file that the first line explicitly says should not be checked into version control, so this should probably be caught by standard practices or .gitignore configuration. The comment should be deleted. While it identifies that user-specific paths are being committed, it uses advisory language ("Consider") rather than being directive, and doesn't clearly specify what action to take. This type of issue (committing generated files) should be caught by standard development practices.
6. examples/flutter/RunAnywhereAI/ios/Flutter/flutter_export_environment.sh:3
  • Draft comment:
    The export script contains absolute paths that are specific to a developer’s environment. Consider using environment variables or relative paths to avoid potential configuration issues.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The file header says "do not edit or check into version control" which means the real issue is that this file shouldn't be in the PR at all, not that the paths need to be changed. The comment is addressing a symptom rather than the root cause. However, according to the rules, I should not comment on things that are obvious or that would be caught by standard practices. The file itself already warns not to check it in. Additionally, the comment doesn't provide a clear, actionable fix - it says "consider using environment variables or relative paths" but this is a generated file, so the developer can't really change how it's structured. The comment is somewhat useful but not actionable given the nature of the file. The comment does identify a real problem (developer-specific paths in version control), and maybe the reviewer intended to suggest that the file should be gitignored rather than suggesting code changes. Perhaps I'm being too strict in interpreting the actionability of the comment. While the comment identifies a real issue, it suggests changing the content of the file ("use environment variables or relative paths") rather than the more appropriate action (don't commit this generated file). The file's own header already warns against checking it into version control, making this comment somewhat redundant. The suggested fix is also not actionable since this is a generated file. The comment should be deleted. It's commenting on a generated file that explicitly states it should not be checked into version control. The suggested fix (using environment variables or relative paths) is not actionable since developers don't control the content of generated files. The real issue is that the file shouldn't be committed at all, which is already stated in the file header.
7. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts:32
  • Draft comment:
    The build script handles downloading pre-built native libraries. Ensure that network issues and version mismatches are properly handled in CI environments.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is asking the PR author to ensure that network issues and version mismatches are handled, which is a form of asking them to double-check things. It doesn't provide a specific suggestion or point out a specific issue in the code.
8. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/proguard-rules.pro:9
  • Draft comment:
    Ensure that these ProGuard keep rules stay updated with any changes in package names or class restructuring to avoid runtime issues.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to ensure that ProGuard keep rules are updated with changes in package names or class restructuring. This is a general reminder to maintain compatibility, which falls under the rule of not asking the author to ensure behavior is intended or tested. It doesn't provide a specific suggestion or point out a specific issue in the code.
9. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/scripts/download-native-libs.sh:124
  • Draft comment:
    The download script verifies checksums which is good. Consider adding timeout handling and more robust error messages for network failures.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a new file being added (the entire script is new). The comment is about line 104 where curl downloads a file. The script already has error handling - it captures HTTP codes, checks for failures, and provides detailed error messages (lines 106-118). The comment suggests "consider adding timeout handling and more robust error messages" but doesn't specify what's missing or inadequate about the current implementation. This feels like a speculative suggestion rather than identifying a concrete problem. The error messages are already quite detailed. While adding a timeout flag to curl might be a valid enhancement, the comment doesn't clearly articulate why it's necessary or what specific problem it solves. This violates the rule about not making speculative comments and being actionable. The script does handle network failures and provides error messages, but perhaps the comment has merit - curl without a timeout could hang indefinitely on slow networks. Maybe the error messages could distinguish between different types of failures (timeout vs 404 vs network unreachable). The comment might be pointing to a legitimate improvement even if not perfectly articulated. While timeouts could be useful, the comment doesn't identify a specific problem with the current implementation. The error handling is already present and reasonably robust. The comment is too vague ("consider adding", "more robust") without explaining what's inadequate. This is a suggestion for potential improvement rather than identifying a clear issue that needs fixing. This comment should be deleted. It's a vague, speculative suggestion that doesn't identify a concrete problem with the code. The script already has error handling and detailed error messages. The comment doesn't provide actionable guidance on what specifically needs to be improved or why.
10. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt:112
  • Draft comment:
    Ensure that backend destruction and cleanup in ONNXCoreService are robust. Consider adding logging for memory usage changes to aid performance debugging.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This comment violates multiple rules. First, it starts with "Ensure that..." which is explicitly called out as a pattern to avoid in the rules. Second, it uses "Consider adding..." which is speculative and not pointing to a definite issue. The destroy() method appears straightforward - it checks the handle and calls the native destroy function. Without evidence of a specific bug or issue (like missing mutex protection, or a race condition), this is just a general suggestion. The comment doesn't point to any specific problem with the current implementation. The logging suggestion is also not about fixing a bug, but about adding optional debugging features. Could there be a legitimate concern about thread safety in the destroy method? I notice other methods use mutex.withLock, but destroy() doesn't. That could be a real issue if destroy() is called concurrently with other operations. However, the comment doesn't specifically mention this - it just vaguely says "ensure robustness" and suggests adding logging. While there might be a legitimate thread safety concern with the destroy() method not using the mutex, the comment doesn't identify this specific issue. Instead, it makes vague statements about "ensuring robustness" and suggests optional logging. If the tool had identified the specific mutex issue, that would be actionable, but this generic comment doesn't meet that bar. This comment should be deleted. It violates the "Ensure that..." rule and makes vague, non-actionable suggestions. It doesn't identify a specific code problem that needs to be fixed. The logging suggestion is optional and not a required change.
11. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt:25
  • Draft comment:
    The RunAnywhereBridge object’s external declarations rely on native libraries. Validate that all required native libraries are packaged and loaded correctly in all target environments.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is asking the PR author to validate that native libraries are packaged and loaded correctly, which falls under the rule of not asking the author to ensure behavior is intended or to double-check things. It doesn't provide a specific code suggestion or point out a specific issue.
12. sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTComponent.kt:35
  • Draft comment:
    STTComponent relies on a registered provider from ModuleRegistry. Ensure that STT service providers are properly registered and handle model management robustly.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
13. sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/stt/STTModels.kt:105
  • Draft comment:
    STTOptions parameters align well with iOS. Consider adding extra validation for newly added parameters if not already enforced elsewhere.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
14. sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt:11
  • Draft comment:
    The equals and hashCode implementations for NativeTTSSynthesisResult are correctly implemented to handle array comparisons.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, as it simply states that the equals and hashCode implementations are correctly implemented. It does not provide any actionable feedback or suggestions for improvement.
15. sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt:1
  • Draft comment:
    The enums for NativeCapability, NativeDeviceType, and NativeResultCode are well defined and map directly to native types. This consistency is excellent.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative and does not provide any actionable feedback or suggestions for improvement. It simply praises the existing code without offering any constructive criticism or guidance.
16. sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt:27
  • Draft comment:
    The NativeCoreService interface provides a comprehensive abstraction for native backends. Verify that all implementations adhere strictly to this contract.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the PR author to verify adherence to an interface contract, which falls under asking the author to double-check or ensure something. This violates the rules.
17. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionScreen.kt:182
  • Draft comment:
    Typographical Notice: The variable naming in the error display section is inconsistent. Previously, the nullable error variable was named 'error' (using error?.let { errorMessage -> ... }), but in the new change it's renamed to 'errorMessage' and then the lambda parameter is called 'error'. This swap of names can lead to confusion. Consider using consistent variable names (e.g., either always 'error' or 'errorMessage').
  • Reason this comment was not posted:
    Comment looked like it was already resolved.
18. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts:8
  • Draft comment:
    Typographical error: In the comment on line 8, "RunAnywhareBridge" appears to be a typo. It should likely read "RunAnywhereBridge".
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a typo in a documentation comment. The rules state "Do NOT comment unless there is clearly a code change required" and "Do NOT make comments that are obvious or unimportant." While this is technically a typo, it's in a comment/documentation, not in actual code. The typo doesn't affect functionality at all - it's purely cosmetic in documentation. The rules emphasize not making obvious or unimportant comments. A single-letter typo in a comment explaining architecture seems like it falls into the "unimportant" category. However, the comment does suggest a clear, actionable fix. But given the emphasis on only keeping comments with STRONG EVIDENCE they are correct and important, a documentation typo seems too minor. While the typo is real and the fix is correct, documentation typos are generally low-priority and might be considered "obvious or unimportant" per the rules. The comment doesn't affect code functionality, and the author likely knows their own naming conventions. This might be too pedantic for a PR review. That's a fair point. This is purely a cosmetic issue in documentation that has zero impact on functionality. While technically correct, it's the kind of minor issue that doesn't warrant blocking or cluttering a PR review. The rules explicitly say not to make obvious or unimportant comments, and a single-letter typo in a comment qualifies as unimportant. This comment should be deleted. While the typo is real, it's a minor cosmetic issue in documentation that doesn't affect functionality. The rules emphasize not making obvious or unimportant comments, and a single-letter typo in a comment falls into that category.

Workflow ID: wflow_b7PRe6bCISsnZ5fW

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.


// MARK: - SDK Event Observation

private fun observeSDKEvents() {
Copy link

Choose a reason for hiding this comment

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

The function observeSDKEvents() is defined but never invoked. Consider invoking it to handle SDK events for transcription.

…timation utilities

- Added TokenCounter object for accurate token counting in text, mirroring iOS functionality.
- Introduced methods for estimating tokens, calculating tokens per second, and splitting token counts in TokenCounter.
- Updated RunAnywhereSDK interface to include token estimation methods, aligning with iOS SDK.
- Added GenerationResult and StreamingResult models for structured output and streaming generation, including performance metrics and validation results.

This commit enhances the SDK's capabilities for text generation and token management, improving overall functionality and user experience.
@sanchitmonga22 sanchitmonga22 marked this pull request as ready for review November 30, 2025 20:53
@sanchitmonga22 sanchitmonga22 changed the title feat: Implement Speech-to-Text and Text-to-Speech screens with corres… [Android-SDK] [Android-Sample] TTS + STT android UI/UX updates Nov 30, 2025
@sanchitmonga22
Copy link
Contributor Author

@ellipsis please review
@greptile please review
@coderabbitai please review

@coderabbitai
Copy link

coderabbitai bot commented Nov 30, 2025

@sanchitmonga22: I'll review the changes in this pull request right away.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sanchitmonga22 sanchitmonga22 changed the title [Android-SDK] [Android-Sample] TTS + STT android UI/UX updates [Kotlin-SDK] [Kotlin-Sample] TTS + STT android UI/UX updates Nov 30, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (9)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt (1)

87-91: Consider whether empty text always indicates failure.

isSuccessful returns false when text is empty. However, some generation scenarios (e.g., structured output that validates correctly but produces no text, or intentionally empty responses) might still be considered successful.

Consider also checking for error states or adding a separate success indicator field if the iOS implementation handles this differently.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/scripts/download-native-libs.sh (3)

130-142: Use portable checksum command.

shasum may not be available on all Linux systems (e.g., Alpine uses sha256sum). Consider adding a fallback:

-    ACTUAL_CHECKSUM=$(shasum -a 256 "$TEMP_ZIP" | awk '{print $1}')
+    if command -v sha256sum &>/dev/null; then
+        ACTUAL_CHECKSUM=$(sha256sum "$TEMP_ZIP" | awk '{print $1}')
+    elif command -v shasum &>/dev/null; then
+        ACTUAL_CHECKSUM=$(shasum -a 256 "$TEMP_ZIP" | awk '{print $1}')
+    else
+        print_error "No SHA256 checksum tool available"
+        exit 1
+    fi

163-166: Silent copy failure may mask issues.

The 2>/dev/null || true suppresses all errors, including real failures (e.g., disk full). Consider logging a warning when no .so files are found:

-            cp "${ABI_DIR}"/*.so "${JNILIBS_DIR}/${ABI}/" 2>/dev/null || true
+            if ls "${ABI_DIR}"/*.so &>/dev/null; then
+                cp "${ABI_DIR}"/*.so "${JNILIBS_DIR}/${ABI}/"
+            else
+                print_step "Warning: No .so files found in ${ABI_DIR}"
+            fi

14-18: Add cleanup trap for failed downloads.

If the script fails mid-execution, TEMP_DIR is left behind. Add a trap after creating the temp directory:

 set -e
 
+cleanup() {
+    [ -n "${TEMP_DIR:-}" ] && rm -rf "$TEMP_DIR"
+}
+trap cleanup EXIT
+
 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt (1)

42-45: Consider sealed class hierarchy for native exceptions.

Per coding guidelines, sealed classes are preferred for type-safe error handling. If you anticipate multiple exception types for native operations, consider:

sealed class NativeBridgeException(
    message: String
) : Exception(message) {
    class OperationFailed(val resultCode: NativeResultCode, message: String? = null) 
        : NativeBridgeException(message ?: "Native operation failed with code: ${resultCode.name}")
    // Future exception types can be added here
}

This is optional if only one exception type is needed. Based on learnings, use sealed classes for error handling.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt (1)

289-293: Consider adding unload methods for STT/TTS components.

The SDK has unloadModel() for LLM but no equivalent for STT/TTS. When users load multiple STT/TTS models sequentially, previous components remain in memory. Consider adding:

suspend fun unloadSTTModel()
suspend fun unloadTTSModel()

Or automatically unload the previous component in loadSTTModel/loadTTSModel before loading a new one.

Also applies to: 1378-1393

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt (1)

37-38: Consider using @Volatile for backendHandle.

Since backendHandle is accessed from multiple threads (both within mutex-protected sections and in property getters), marking it @Volatile ensures visibility of writes across threads.

-    private var backendHandle: Long = 0
+    @Volatile
+    private var backendHandle: Long = 0
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt (1)

232-235: Consider making destroy() a suspend function.

Making destroy() suspend would allow implementations to properly synchronize cleanup without blocking (e.g., using mutex in coroutine context). The current non-suspend signature forces implementations like ONNXCoreService to either skip synchronization or use runBlocking.

     /**
      * Destroy the backend and release all resources.
      */
-    fun destroy()
+    suspend fun destroy()
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt (1)

19-19: Consider @Volatile for isLibraryLoaded.

While @Synchronized on loadLibrary() ensures safe writes, reads via isLoaded() aren't synchronized. Adding @Volatile ensures visibility of the write to other threads reading outside the synchronized block.

-    private var isLibraryLoaded = false
+    @Volatile
+    private var isLibraryLoaded = false
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 463505f and 65d34f5.

📒 Files selected for processing (14)
  • examples/android/RunAnywhereAI/app/build.gradle.kts (2 hunks)
  • examples/android/RunAnywhereAI/settings.gradle.kts (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/.gitignore (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/VERSION (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/scripts/download-native-libs.sh (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt (1 hunks)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt (1 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt (6 hunks)
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/VERSION
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/.gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts
🧰 Additional context used
📓 Path-based instructions (1)
sdk/runanywhere-kotlin/**/src/**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

sdk/runanywhere-kotlin/**/src/**/*.kt: All business logic, protocols, interfaces, and structures MUST be defined in commonMain/ for Kotlin Multiplatform projects. Platform-specific implementations must use clear prefixes like AndroidTTSService.kt, JvmTTSService.kt, etc.
NEVER make assumptions when implementing KMP code. ALWAYS refer to the iOS implementation as the definitive source of truth. Check the iOS implementation, copy the logic exactly, and adapt only for Kotlin syntax.
Use expect/actual ONLY for platform-specific implementations, not for business logic. Put all business logic in commonMain/.
Use Flow instead of AsyncSequence for reactive streams in Kotlin Multiplatform code.
Use coroutines and suspend functions instead of async/await patterns for asynchronous operations.
Use sealed classes for type-safe error handling in Kotlin code.
Always use data classes and structured types (enums, sealed classes) instead of strings for models and configuration.
Use the ModuleRegistry provider pattern for extensibility and plugin architecture instead of hard-coded dependencies.
Use EventBus for component communication instead of direct coupling between components.
Use Service Container pattern for centralized dependency injection with lazy initialization.
Use lazy initialization for service dependencies to avoid memory pressure and allow garbage collection.

Files:

  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
🧠 Learnings (16)
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use the `ModuleRegistry` provider pattern for extensibility and plugin architecture instead of hard-coded dependencies.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/androidMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/jvmMain/**/*.kt : Use platform-specific optimizations in their respective source directories: `androidMain/` for Android optimizations, `jvmMain/` for JVM optimizations.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : Android minSdk must be 24 or later for Kotlin Multiplatform SDK.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : JVM target must be 17 or later for Kotlin Multiplatform SDK.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : Kotlin version must be 2.1.21 or later for the Kotlin Multiplatform SDK.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use lazy initialization for service dependencies to avoid memory pressure and allow garbage collection.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use coroutines and suspend functions instead of async/await patterns for asynchronous operations.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : All business logic, protocols, interfaces, and structures MUST be defined in `commonMain/` for Kotlin Multiplatform projects. Platform-specific implementations must use clear prefixes like `AndroidTTSService.kt`, `JvmTTSService.kt`, etc.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use `expect/actual` ONLY for platform-specific implementations, not for business logic. Put all business logic in `commonMain/`.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • examples/android/RunAnywhereAI/settings.gradle.kts
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use Service Container pattern for centralized dependency injection with lazy initialization.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt
  • sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/components/**/*.kt : Implement proper component lifecycle management with initialization, state tracking, and cleanup in BaseComponent.

Applied to files:

  • examples/android/RunAnywhereAI/app/build.gradle.kts
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
📚 Learning: 2025-10-17T22:19:36.568Z
Learnt from: shubhammalhotra28
Repo: RunanywhereAI/runanywhere-sdks PR: 119
File: README.md:176-176
Timestamp: 2025-10-17T22:19:36.568Z
Learning: The RunAnywhere SDK package repository is located at `https://github.com/RunanywhereAI/runanywhere-sdks`. The repository was moved from `sdks` to `runanywhere-sdks`, so the correct URL to reference in documentation and installation instructions is `https://github.com/RunanywhereAI/runanywhere-sdks`.

Applied to files:

  • examples/android/RunAnywhereAI/settings.gradle.kts
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use sealed classes for type-safe error handling in Kotlin code.

Applied to files:

  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Always use data classes and structured types (enums, sealed classes) instead of strings for models and configuration.

Applied to files:

  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt
  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/*.kt : Use EventBus for component communication instead of direct coupling between components.

Applied to files:

  • sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
🧬 Code graph analysis (1)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt (1)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt (2)
  • estimateTokenCount (257-257)
  • estimateTokenCount (1554-1556)
🪛 detekt (1.23.8)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt

[warning] 1426-1426: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 1465-1465: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt

[warning] 36-36: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 42-42: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🔇 Additional comments (17)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt (3)

32-36: LGTM!

Well-structured data class with appropriate defaults and immutable properties.


106-127: Good factory method for testing and simple use cases.

The simple() factory provides reasonable defaults and correctly calculates tokens per second. The hardcoded ExecutionTarget.ON_DEVICE is appropriate for the stated testing use case.


154-173: LGTM!

Good use of Flow<String> for streaming as per coding guidelines. The collectText() implementation is straightforward and efficient with StringBuilder. The documentation example clearly demonstrates the intended usage pattern.

examples/android/RunAnywhereAI/app/build.gradle.kts (2)

33-36: Verify device compatibility impact of arm64-v8a only ABI filter.

Restricting to arm64-v8a excludes 32-bit ARM devices (armeabi-v7a) and x86 emulators. This is fine for development, but ensure this limitation is documented for users and consider adding x86_64 for emulator testing.


191-193: LGTM!

The ONNX module dependency is correctly added alongside other SDK modules.

examples/android/RunAnywhereAI/settings.gradle.kts (1)

41-44: LGTM!

Module inclusion follows the established pattern with clear documentation of its purpose.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/BridgeResults.kt (1)

7-28: LGTM!

Correct implementation of equals/hashCode for data class containing FloatArray. Using contentEquals and contentHashCode ensures proper value-based comparison.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt (1)

22-55: LGTM - Token estimation heuristic is well-documented.

The approximation approach is reasonable for pre-tokenizer usage with clear documentation of assumptions (GPT-like tokenization patterns).

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/Capability.kt (2)

17-19: Inconsistent fromValue null-safety behavior across enums.

  • NativeCapability.fromValue returns null for unknown values
  • NativeDeviceType.fromValue returns CPU as default
  • NativeResultCode.fromValue returns ERROR_UNKNOWN as default

This inconsistency requires callers to handle each enum differently. Consider documenting the rationale or unifying the approach. If intentional (e.g., unknown capability is a hard error, but unknown device defaults to CPU), add KDoc comments explaining why.

Also applies to: 37-39, 62-64


46-65: LGTM - Well-structured result code enum.

Clear mapping to C API codes with convenient isSuccess property.

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt (2)

157-190: LGTM - STT/TTS model management API surface.

Clean interface additions matching iOS API patterns with proper KDoc documentation.


1544-1557: LGTM!

Clean delegation to TokenCounter utility following the established pattern.

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/ONNXCoreService.kt (2)

353-379: Companion object utilities are well-structured.

The static-like utilities (getAvailableBackends, getVersion, extractArchive) correctly ensure the library is loaded before each call, making them safe for standalone usage.


40-43: Thread safety and suspend function design looks good.

The pattern of withContext(Dispatchers.IO) + mutex.withLock + ensureInitialized() is consistently applied across model loading and inference operations. This provides proper thread safety and ensures native I/O doesn't block the main dispatcher.

Also applies to: 119-131

sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/native/bridge/NativeCoreService.kt (1)

27-236: Well-designed interface correctly placed in commonMain/.

The NativeCoreService interface follows Kotlin Multiplatform best practices:

  • Placed in commonMain/ as the central contract (per coding guidelines)
  • Uses suspend functions for I/O-bound operations
  • Uses structured types (NativeCapability, NativeDeviceType, etc.) instead of primitives
  • Comprehensive KDoc documentation

Based on learnings, this correctly follows the guideline that "All business logic, protocols, interfaces, and structures MUST be defined in commonMain/."

sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt (2)

17-17: Good JNI bridge design with proper visibility.

The internal visibility correctly encapsulates this as an implementation detail. The organized grouping of external functions by feature area (Backend Lifecycle, Text Generation, STT, TTS, VAD, Embeddings, Diarization, Utility) makes the API surface clear and maintainable.

Also applies to: 61-299


25-50: Idempotent library loading pattern is correct.

The @Synchronized annotation combined with the early return on isLibraryLoaded ensures thread-safe, idempotent library loading. The exception propagation for the primary library (runanywhere_jni) while allowing optional dependencies to fail silently is a reasonable approach.

Comment on lines +80 to +81
override val isInitialized: Boolean
get() = backendHandle != 0L && RunAnywhereBridge.nativeIsInitialized(backendHandle)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unsynchronized access to backendHandle in property getter.

isInitialized reads backendHandle and calls a native method without mutex protection. If destroy() is called concurrently, this could read a stale handle or pass an invalidated handle to native code.

Consider either:

  1. Making this property access synchronized
  2. Using @Volatile on backendHandle (provides visibility but not atomicity for the compound check)
  3. Documenting that callers must not call property getters concurrently with destroy()

The same concern applies to other property getters: supportedCapabilities (line 83-89), deviceType (line 96-100), memoryUsage (line 102-106), isSTTModelLoaded (line 133-134), isTTSModelLoaded (line 188-189), isVADModelLoaded (line 251-252), isEmbeddingModelLoaded (line 308-309), supportsSTTStreaming (line 167-168), and embeddingDimensions (line 334-338).

Comment on lines +34 to +44
try {
System.loadLibrary("runanywhere_bridge")
} catch (e: UnsatisfiedLinkError) {
// May already be loaded or linked statically
}

try {
System.loadLibrary("onnxruntime")
} catch (e: UnsatisfiedLinkError) {
// May already be loaded
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Swallowed exceptions lose debugging context.

Static analysis correctly flags that caught exceptions are swallowed. While the intent to handle "already loaded" cases is valid, silently ignoring these errors makes debugging harder when library loading actually fails for other reasons.

Consider logging the exception or distinguishing between expected and unexpected failures:

             // Also load dependencies if needed
             try {
                 System.loadLibrary("runanywhere_bridge")
             } catch (e: UnsatisfiedLinkError) {
-                // May already be loaded or linked statically
+                // May already be loaded or linked statically - log for debugging
+                // Log.d("RunAnywhereBridge", "runanywhere_bridge not loaded separately: ${e.message}")
             }

             try {
                 System.loadLibrary("onnxruntime")
             } catch (e: UnsatisfiedLinkError) {
-                // May already be loaded
+                // May already be loaded - log for debugging
+                // Log.d("RunAnywhereBridge", "onnxruntime not loaded separately: ${e.message}")
             }

Alternatively, check if the library is already loaded before attempting to load it, if the platform provides such a mechanism.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 detekt (1.23.8)

[warning] 36-36: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)


[warning] 42-42: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🤖 Prompt for AI Agents
In
sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/src/jvmAndroidMain/kotlin/com/runanywhere/sdk/core/onnx/RunAnywhereBridge.kt
around lines 34–44, the catch blocks currently swallow UnsatisfiedLinkError
which loses debugging context; modify each catch to log the exception (including
message and stacktrace) and only suppress it when you can positively determine
the error is the expected "already loaded or statically linked" case (for
example by checking the exception message or using a platform API to test if the
library is already loaded), otherwise rethrow the exception so real load
failures surface; ensure logs include clear context (which library failed) and
use the project logger or Android Log as appropriate.

Comment on lines +77 to +91
fun splitTokenCounts(
fullText: String,
thinkingContent: String?,
responseContent: String
): Triple<Int?, Int, Int> {
val responseTokens = estimateTokenCount(responseContent)

return if (!thinkingContent.isNullOrEmpty()) {
val thinkingTokens = estimateTokenCount(thinkingContent)
val totalTokens = thinkingTokens + responseTokens
Triple(thinkingTokens, responseTokens, totalTokens)
} else {
Triple(null, responseTokens, responseTokens)
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused fullText parameter.

The fullText parameter is never used in splitTokenCounts. This may indicate incomplete implementation or a refactoring artifact.

 fun splitTokenCounts(
-    fullText: String,
     thinkingContent: String?,
     responseContent: String
 ): Triple<Int?, Int, Int> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun splitTokenCounts(
fullText: String,
thinkingContent: String?,
responseContent: String
): Triple<Int?, Int, Int> {
val responseTokens = estimateTokenCount(responseContent)
return if (!thinkingContent.isNullOrEmpty()) {
val thinkingTokens = estimateTokenCount(thinkingContent)
val totalTokens = thinkingTokens + responseTokens
Triple(thinkingTokens, responseTokens, totalTokens)
} else {
Triple(null, responseTokens, responseTokens)
}
}
fun splitTokenCounts(
thinkingContent: String?,
responseContent: String
): Triple<Int?, Int, Int> {
val responseTokens = estimateTokenCount(responseContent)
return if (!thinkingContent.isNullOrEmpty()) {
val thinkingTokens = estimateTokenCount(thinkingContent)
val totalTokens = thinkingTokens + responseTokens
Triple(thinkingTokens, responseTokens, totalTokens)
} else {
Triple(null, responseTokens, responseTokens)
}
}
🤖 Prompt for AI Agents
In
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/generation/TokenCounter.kt
around lines 77 to 91, the function splitTokenCounts declares an unused fullText
parameter; remove fullText from the function signature and update the
implementation signature to only accept thinkingContent and responseContent (or
reorder/rename as needed), and then update all call sites across the codebase to
stop passing fullText (or pass the appropriate value into the remaining
parameters). Run a compile to find and fix any remaining references and adjust
any tests or documentation accordingly.

Comment on lines +21 to +25
companion object {
fun fromValue(value: String): HardwareAcceleration {
return values().find { it.value == value } ?: CPU
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Kotlin enum values() vs entries deprecation Kotlin 1.9

💡 Result:

Short answer

  • Kotlin 1.9 makes enum class.entries the stable, preferred replacement for the synthetic values() function. Use entries (a List/EnumEntries) instead of values() (an Array) for better performance and safer semantics. [1][2]

Key details

  • entries was stabilized in 1.9; values() continues to work but you should migrate to entries. Example:
    • Before: MyEnum.values()
    • After: MyEnum.entries
      Note: entries is a List (EnumEntries), not an Array—if you need an Array, call .toTypedArray(). [1][2]
  • For Java callers, Kotlin generates getEntries() as the recommended replacement for values(). IDE quick-fixes can convert usages. [3]
  • A related change: the generic enumValues() replacement is enumEntries() (experimental in 1.9.20); enumValues() still works but enumEntries is more efficient (returns a shared list instead of allocating a new array each call). [3]
  • Also watch related 1.9 enum compatibility changes (e.g., external enums deprecation, decls like declaringClass). See migration notes if you maintain cross-language APIs. [1][2]

Sources

  • Kotlin 1.9 "What's new" (entries stabilization & migration notes). [1]
  • Kotlin 1.9.20 notes (enumEntries() experimental). [2]
  • IntelliJ/JetBrains inspection docs showing automatic replacement and Java getEntries recommendation. [3]

🏁 Script executed:

# Check the project's Kotlin version requirement
cd sdk/runanywhere-kotlin
find . -name "build.gradle" -o -name "build.gradle.kts" -o -name "gradle.properties" | head -5

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 261


🏁 Script executed:

# Check Kotlin version in main build.gradle.kts
head -50 build.gradle.kts

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 1746


🏁 Script executed:

# Also check gradle.properties for version info
cat gradle.properties

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 407


🏁 Script executed:

# Check Kotlin version in SDK module
cat sdk/runanywhere-kotlin/build.gradle.kts | head -80

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 2488


🏁 Script executed:

# Check the version catalog for Kotlin version
find . -name "libs.versions.toml" -o -name "versions.toml" | xargs cat 2>/dev/null

Repository: RunanywhereAI/runanywhere-sdks

Length of output: 18097


Use entries instead of values() for enum iteration.

values() is deprecated in Kotlin 1.9+, and the project uses Kotlin 2.1.21. Use entries (a List) instead of values() (an Array) for better performance and to align with current best practices.

Additionally, silently defaulting to CPU for unknown values may mask configuration errors. Consider throwing an IllegalArgumentException or returning null to make invalid input explicit.

    companion object {
        fun fromValue(value: String): HardwareAcceleration {
-            return values().find { it.value == value } ?: CPU
+            return entries.find { it.value == value } ?: CPU
        }
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
companion object {
fun fromValue(value: String): HardwareAcceleration {
return values().find { it.value == value } ?: CPU
}
}
companion object {
fun fromValue(value: String): HardwareAcceleration {
return entries.find { it.value == value } ?: CPU
}
}
🤖 Prompt for AI Agents
In
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/models/GenerationResult.kt
around lines 21 to 25, replace the deprecated values() enum iteration with
entries and stop silently defaulting to CPU for unknown inputs: change the
function to search HardwareAcceleration.entries for a matching .value and, if
none found, throw an IllegalArgumentException (or alternatively return null if
you prefer nullable API) with a clear message including the invalid value so
invalid configuration is explicit.

Comment on lines +1401 to +1431
override suspend fun loadSTTModel(modelId: String) {
requireInitialized()

EventBus.publish(SDKModelEvent.LoadStarted(modelId))

try {
// Get model info for lifecycle tracking
val modelInfo = serviceContainer.modelRegistry?.getModel(modelId)
val modelName = modelInfo?.name ?: modelId

logger.info("Loading STT model: $modelName ($modelId)")

// Create STT configuration
val sttConfig = com.runanywhere.sdk.components.stt.STTConfiguration(modelId = modelId)

// Create and initialize STT component
val sttComponent = com.runanywhere.sdk.components.stt.STTComponent(sttConfig)
sttComponent.initialize()

// Store the component for later use
_loadedSTTComponent = sttComponent

logger.info("✅ STT model loaded successfully: $modelName")
EventBus.publish(SDKModelEvent.LoadCompleted(modelId))

} catch (e: Exception) {
logger.error("Failed to load STT model: $modelId", e)
EventBus.publish(SDKModelEvent.LoadFailed(modelId, e))
throw SDKError.ModelLoadingFailed("Failed to load STT model: ${e.message}")
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Preserve original exception as cause for debugging.

The caught exception is logged and used in the error message, but the original stack trace is lost when wrapping in SDKError.ModelLoadingFailed. Chain the original exception as the cause:

-            throw SDKError.ModelLoadingFailed("Failed to load STT model: ${e.message}")
+            throw SDKError.ModelLoadingFailed("Failed to load STT model: ${e.message}", e)

This requires SDKError.ModelLoadingFailed to accept a cause parameter. If it doesn't, consider adding one.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 detekt (1.23.8)

[warning] 1426-1426: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🤖 Prompt for AI Agents
In
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
around lines 1401 to 1431, preserve the original exception when wrapping it by
updating the thrown SDKError.ModelLoadingFailed to accept and include the caught
exception as its cause; if the SDKError.ModelLoadingFailed constructor does not
currently accept a cause, add an overload or parameter to accept a Throwable
cause, then change the throw to pass the caught exception (e) as that cause
while keeping the existing message and logging/Events intact.

Comment on lines +1440 to +1470
override suspend fun loadTTSModel(modelId: String) {
requireInitialized()

EventBus.publish(SDKModelEvent.LoadStarted(modelId))

try {
// Get model info for lifecycle tracking
val modelInfo = serviceContainer.modelRegistry?.getModel(modelId)
val modelName = modelInfo?.name ?: modelId

logger.info("Loading TTS model: $modelName ($modelId)")

// Create TTS configuration
val ttsConfig = com.runanywhere.sdk.components.TTSConfiguration(modelId = modelId)

// Create and initialize TTS component
val ttsComponent = com.runanywhere.sdk.components.TTSComponent(ttsConfig)
ttsComponent.initialize()

// Store the component for later use
_loadedTTSComponent = ttsComponent

logger.info("✅ TTS model loaded successfully: $modelName")
EventBus.publish(SDKModelEvent.LoadCompleted(modelId))

} catch (e: Exception) {
logger.error("Failed to load TTS model: $modelId", e)
EventBus.publish(SDKModelEvent.LoadFailed(modelId, e))
throw SDKError.ModelLoadingFailed("Failed to load TTS model: ${e.message}")
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same issue: Preserve exception cause in TTS model loading.

Apply the same fix as STT:

-            throw SDKError.ModelLoadingFailed("Failed to load TTS model: ${e.message}")
+            throw SDKError.ModelLoadingFailed("Failed to load TTS model: ${e.message}", e)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override suspend fun loadTTSModel(modelId: String) {
requireInitialized()
EventBus.publish(SDKModelEvent.LoadStarted(modelId))
try {
// Get model info for lifecycle tracking
val modelInfo = serviceContainer.modelRegistry?.getModel(modelId)
val modelName = modelInfo?.name ?: modelId
logger.info("Loading TTS model: $modelName ($modelId)")
// Create TTS configuration
val ttsConfig = com.runanywhere.sdk.components.TTSConfiguration(modelId = modelId)
// Create and initialize TTS component
val ttsComponent = com.runanywhere.sdk.components.TTSComponent(ttsConfig)
ttsComponent.initialize()
// Store the component for later use
_loadedTTSComponent = ttsComponent
logger.info("✅ TTS model loaded successfully: $modelName")
EventBus.publish(SDKModelEvent.LoadCompleted(modelId))
} catch (e: Exception) {
logger.error("Failed to load TTS model: $modelId", e)
EventBus.publish(SDKModelEvent.LoadFailed(modelId, e))
throw SDKError.ModelLoadingFailed("Failed to load TTS model: ${e.message}")
}
}
override suspend fun loadTTSModel(modelId: String) {
requireInitialized()
EventBus.publish(SDKModelEvent.LoadStarted(modelId))
try {
// Get model info for lifecycle tracking
val modelInfo = serviceContainer.modelRegistry?.getModel(modelId)
val modelName = modelInfo?.name ?: modelId
logger.info("Loading TTS model: $modelName ($modelId)")
// Create TTS configuration
val ttsConfig = com.runanywhere.sdk.components.TTSConfiguration(modelId = modelId)
// Create and initialize TTS component
val ttsComponent = com.runanywhere.sdk.components.TTSComponent(ttsConfig)
ttsComponent.initialize()
// Store the component for later use
_loadedTTSComponent = ttsComponent
logger.info("✅ TTS model loaded successfully: $modelName")
EventBus.publish(SDKModelEvent.LoadCompleted(modelId))
} catch (e: Exception) {
logger.error("Failed to load TTS model: $modelId", e)
EventBus.publish(SDKModelEvent.LoadFailed(modelId, e))
throw SDKError.ModelLoadingFailed("Failed to load TTS model: ${e.message}", e)
}
}
🧰 Tools
🪛 detekt (1.23.8)

[warning] 1465-1465: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🤖 Prompt for AI Agents
In
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/public/RunAnywhere.kt
around lines 1440 to 1470, the catch block logs and rethrows
SDKError.ModelLoadingFailed without preserving the original exception as the
cause; update the catch to pass the caught exception into both the log/event (if
event supports it) and into the thrown SDKError.ModelLoadingFailed so the
original stacktrace is preserved (e.g., include e as the cause/inner exception
when constructing SDKError.ModelLoadingFailed and keep logger.error(..., e)
as-is).

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

37 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 65d34f5 in 13 minutes and 40 seconds. Click for details.
  • Reviewed 9291 lines of code in 37 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts:8
  • Draft comment:
    Typo: 'RunAnywhareBridge' appears to be misspelled. Consider changing it to 'RunAnywhereBridge' for consistency with the module naming.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 30% vs. threshold = 50% This is a comment about a typo in documentation (a comment block). The file is entirely new (all additions), so technically this is "about changes" since the whole file is new. However, I need to consider: 1) Is this actionable? Yes, it's a simple typo fix. 2) Is it important? It's a documentation typo, relatively minor but does affect clarity. 3) Does it require code changes? Yes, but only to a comment. 4) Is it clearly correct? Looking at the pattern, "RunAnywhere" is used everywhere else, so "RunAnywhareBridge" does appear to be a typo. However, the rules say "Do NOT comment unless there is clearly a code change required" and "Do NOT make comments that are obvious or unimportant." A typo in a comment is relatively unimportant and might be considered obvious. The rules also emphasize only keeping comments with STRONG EVIDENCE of correctness and actionable issues. While this is technically a valid typo, it's only in a documentation comment, not in actual code. The rules emphasize not making obvious or unimportant comments. A typo in a comment that doesn't affect functionality might fall into the "unimportant" category. Additionally, without seeing the actual implementation files, I can't be 100% certain what the correct name should be - maybe "RunAnywhareBridge" is intentional, though unlikely. The typo is in documentation that describes the architecture, which is important for developers understanding the system. However, it's still just a comment typo and not a functional issue. Given the rules emphasize removing comments that aren't clearly important and the instruction to err on the side of deletion when unsure, this comment about a documentation typo should probably be removed as it's relatively minor. This comment identifies a likely typo in documentation, but it's a minor issue in a comment rather than functional code. Given the rules to avoid obvious/unimportant comments and to default to deletion when uncertain, this comment should be removed.

Workflow ID: wflow_RGiuUrqn0JiOgBO7

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 65d34f5 in 13 minutes and 41 seconds. Click for details.
  • Reviewed 9291 lines of code in 37 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. sdk/runanywhere-kotlin/modules/runanywhere-core-onnx/build.gradle.kts:8
  • Draft comment:
    Typo: "RunAnywhareBridge" should likely be "RunAnywhereBridge" for consistency.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% This is a comment about documentation/comments, not actual code. The rules state I should not comment on things that are "obvious or unimportant." A typo in a comment is relatively minor. However, I need to consider: 1) Is this actually a typo? Looking at the context, "RunAnywhere" is the product name, so "RunAnywhereBridge" would be the expected spelling. "RunAnywhareBridge" does look like a typo. 2) But this is just in a documentation comment explaining architecture - it's not in actual code that would cause bugs. 3) The rules say comments should be about code changes that are required, not just informative. A typo in documentation is more of a "nice to have" fix rather than a required code change. 4) Without seeing other files, I cannot verify what the actual class name is - maybe it really is "RunAnywhareBridge" intentionally? I don't have strong evidence either way. I cannot see the actual implementation files to verify what the correct name of the bridge class actually is. It's possible "RunAnywhareBridge" is intentional, or it could be that the actual class also has this typo. Without cross-file context, I cannot be certain this is actually wrong. Additionally, this is just documentation/comments, not functional code, making it lower priority. While I cannot verify the correct spelling without seeing other files, "RunAnywhareBridge" does appear to be inconsistent with the "RunAnywhere" branding used throughout the rest of the file. However, the rules explicitly state to ignore issues that require cross-file context, and I should only keep comments with strong evidence they're correct. Since this is just documentation and I lack definitive proof, I should delete it. This comment is about a potential typo in documentation, not functional code. I cannot verify the correct spelling without seeing other files (the rules say to ignore cross-file issues). The comment doesn't point to a clearly required code change - it's more of a minor documentation improvement. Following the principle that I need strong evidence to keep a comment, I should delete this.

Workflow ID: wflow_3rr2wOf5qoayreyc

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

- Added Flutter auto-generated files to .gitignore to prevent local paths from being tracked.
- Refactored SettingsViewModel to optimize model filtering and storage size calculation.
- Updated SpeechToTextScreen to improve loading state logic based on model status.
- Adjusted TextToSpeechViewModel to dynamically calculate character count from input text.
- Enhanced TranscriptionViewModel to start observing SDK events upon initialization.
- Modified VoiceAssistantScreen to improve icon handling and animation behavior.

These changes streamline the project structure and enhance the functionality of various components.
@sanchitmonga22 sanchitmonga22 merged commit b303070 into main Nov 30, 2025
3 of 7 checks passed
Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed 14ae81c in 1 minute and 36 seconds. Click for details.
  • Reviewed 131 lines of code in 7 files
  • Skipped 1 files when reviewing.
  • Skipped posting 8 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/settings/SettingsViewModel.kt:275
  • Draft comment:
    Using an intermediate 'filteredModels' variable improves readability and ensures the model storage size is calculated consistently.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/stt/SpeechToTextScreen.kt:73
  • Draft comment:
    Replacing a null check on selectedModelName with '!uiState.isModelLoaded' gives a more direct indication of the model’s readiness.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
3. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/tts/TextToSpeechViewModel.kt:19
  • Draft comment:
    Computing the characterCount using the length of the default input text improves maintainability if the default string changes.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
4. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/TranscriptionViewModel.kt:122
  • Draft comment:
    Calling observeSDKEvents() during initialization ensures the ViewModel starts receiving SDK events promptly.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
5. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt:568
  • Draft comment:
    Differentiating between Icons.Filled.Info and Icons.Outlined.Info improves visual feedback for toggling model info.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
6. examples/android/RunAnywhereAI/app/src/main/java/com/runanywhere/runanywhereai/presentation/voice/VoiceAssistantScreen.kt:895
  • Draft comment:
    Switching the repeatMode from Restart to Reverse produces a smoother pulsing effect for the recording button.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
7. examples/flutter/RunAnywhereAI/ios/Flutter/Generated.xcconfig:1
  • Draft comment:
    Auto-generated Flutter config file has been removed; ensure it is added to .gitignore to prevent future accidental commits.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
8. examples/flutter/RunAnywhereAI/ios/Flutter/flutter_export_environment.sh:1
  • Draft comment:
    Removed auto-generated Flutter export environment script; confirm such generated files are ignored by version control.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_fUmmeNbfTSUPnJ2D

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants