feat: support to build for windows and add proxy when do http request or download modals#497
feat: support to build for windows and add proxy when do http request or download modals#497peilinok wants to merge 3 commits intoRunanywhereAI:mainfrom
Conversation
|
Too many files changed for review. ( |
📝 WalkthroughWalkthroughThis PR adds first-class Windows support across the SDK and example app, implements scoped proxy configuration and HTTP helpers, introduces vision/camera/VLM abstractions and services, updates many Flutter UIs to gate features by runtime capabilities, and provides Windows build CMake/scripts, plugins, and tests. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Flutter App
participant Plugin as Flutter Windows Plugin (C API)
participant DLL as Native Backend DLL (rac_commons / backend)
participant SDK as runanywhere native backend (ONNX/llamacpp)
participant FS as Filesystem
App->>Plugin: MethodChannel call (e.g., loadVLMModel / getPlatformVersion)
Plugin->>DLL: Invoke C API / bridge call
DLL->>SDK: Call backend functions (loadModel/processImage)
SDK->>FS: Read model files (.gguf) / resolve paths
SDK-->>DLL: Stream results / tokens
DLL-->>Plugin: Bridge results via C API
Plugin-->>App: Send results via MethodChannel / stream
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit c3b45a9. Configure here.
There was a problem hiding this comment.
Pull request overview
Adds initial Windows support across the Flutter SDK packages and the Flutter example app, plus introduces proxy-aware HTTP plumbing for example app requests and SDK model downloads, and improves Windows path handling for VLM model resolution.
Changes:
- Add Windows Flutter plugin implementations + CMake bundling for
runanywhere,runanywhere_llamacpp, andrunanywhere_onnx. - Introduce proxy configuration + proxy-aware HTTP service in the Flutter example app, and expose a download-only HTTP client factory hook in the Flutter SDK.
- Improve Windows compatibility in path handling (VLM resolution, directory listing), auth logging redaction, and Windows build tooling for
runanywhere-commons.
Reviewed changes
Copilot reviewed 99 out of 101 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin_c_api.cpp | Adds Windows C API registrar for ONNX Flutter plugin. |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin.h | Declares Windows ONNX plugin class. |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin.cpp | Implements Windows ONNX plugin method channel handlers (version/name). |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/windows/include/runanywhere_onnx/runanywhere_onnx_plugin_c_api.h | Exposes ONNX plugin C API entrypoint for Windows. |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/windows/CMakeLists.txt | Builds ONNX Windows plugin and bundles runtime DLLs from commons dist. |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/pubspec.yaml | Registers Windows plugin class for ONNX package. |
| sdk/runanywhere-flutter/packages/runanywhere_onnx/lib/native/onnx_bindings.dart | Loads ONNX backend DLL on Windows. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin_c_api.cpp | Adds Windows C API registrar for LlamaCPP Flutter plugin. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin.h | Declares Windows LlamaCPP plugin class. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin.cpp | Implements Windows LlamaCPP plugin method channel handlers (version/name). |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/include/runanywhere_llamacpp/runanywhere_llamacpp_plugin_c_api.h | Exposes LlamaCPP plugin C API entrypoint for Windows. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/CMakeLists.txt | Builds LlamaCPP Windows plugin and bundles rac_backend_llamacpp.dll. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/pubspec.yaml | Registers Windows plugin class for LlamaCPP package. |
| sdk/runanywhere-flutter/packages/runanywhere_llamacpp/lib/native/llamacpp_bindings.dart | Loads LlamaCPP backend DLL on Windows. |
| sdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin_c_api.cpp | Adds Windows C API registrar for core Flutter plugin. |
| sdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin.h | Declares Windows core plugin class. |
| sdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin.cpp | Implements Windows core plugin method channel handlers (SDK/commons version). |
| sdk/runanywhere-flutter/packages/runanywhere/windows/include/runanywhere/runanywhere_plugin_c_api.h | Exposes core plugin C API entrypoint for Windows. |
| sdk/runanywhere-flutter/packages/runanywhere/windows/CMakeLists.txt | Builds core Windows plugin and bundles rac_commons.dll. |
| sdk/runanywhere-flutter/packages/runanywhere/pubspec.yaml | Registers Windows plugin class for core runanywhere package. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/public/runanywhere.dart | Adds download HTTP client factory configuration API; refactors VLM file resolution usage. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/native/platform_loader.dart | Changes Windows DLL search path behavior for native loading. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_tts.dart | Captures FFI handle address before isolate call (safety). |
| sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_stt.dart | Captures FFI handle address before isolate call (safety). |
| sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_model_registry.dart | Normalizes Windows path separators when listing directory entries. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_auth.dart | Redacts auth request/response logging metadata; fixes UTF-8 buffer copying; aligns SDK config struct for FFI. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/internal/vlm_file_resolution.dart | Adds Windows-safe VLM path basename + main/mmproj resolution helpers. |
| sdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dart | Adds injectable HTTP client factory and improves multi-file download progress calculation/cleanup. |
| sdk/runanywhere-flutter/packages/runanywhere/test/vlm_file_resolution_test.dart | Adds tests for Windows path basename and VLM model/mmproj resolution. |
| sdk/runanywhere-flutter/packages/runanywhere/test/download_service_test.dart | Adds tests for multi-file progress calculation and per-file size estimation. |
| sdk/runanywhere-flutter/packages/runanywhere/test/dart_bridge_auth_test.dart | Adds tests for auth environment mapping, log metadata redaction, and UTF-8 buffer copy. |
| sdk/runanywhere-flutter/packages/runanywhere/test/auth_sdk_config_ffi_layout_test.dart | Ensures auth/env FFI config structs match layout size. |
| sdk/runanywhere-flutter/packages/runanywhere/README.md | Documents Windows setup preview for Flutter SDK. |
| sdk/runanywhere-commons/tests/test_download_orchestrator.cpp | Adds test ensuring .gguf model selection skips mmproj auxiliary files. |
| sdk/runanywhere-commons/src/infrastructure/extraction/rac_extraction_stub.cpp | Adds stub extraction implementation for builds where native extraction is disabled. |
| sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp | Adds Windows filesystem traversal and improves model file detection + nested dir selection. |
| sdk/runanywhere-commons/src/core/rac_core.cpp | Restricts diffusion registry init/cleanup to iOS/macOS only. |
| sdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cpp | Makes embeddings registration conditional and improves error handling/logging. |
| sdk/runanywhere-commons/src/backends/onnx/onnx_backend.cpp | Fixes directory listing logging to avoid relying on dirent.d_type. |
| sdk/runanywhere-commons/src/backends/onnx/CMakeLists.txt | Adds compile-time RAC_ONNX_EMBEDDINGS_AVAILABLE flag; notes Windows build path. |
| sdk/runanywhere-commons/src/backends/llamacpp/CMakeLists.txt | Adds/adjusts Windows CPU-only configuration and build flags; gates VLM mtmd on RAC_BUILD_VLM. |
| sdk/runanywhere-commons/scripts/windows/download-sherpa-onnx.bat | Improves download retries, extraction robustness, and validates expected Sherpa artifacts. |
| sdk/runanywhere-commons/scripts/build-windows.bat | Simplifies Windows build pipeline and copies produced DLLs into dist. |
| sdk/runanywhere-commons/README.md | Documents Windows build usage and ONNX dependency workflow. |
| sdk/runanywhere-commons/CMakeLists.txt | Adds RAC_BUILD_VLM option. |
| examples/flutter/RunAnywhereAI/windows/runner/win32_window.h | Adds Win32 window implementation for Windows runner. |
| examples/flutter/RunAnywhereAI/windows/runner/win32_window.cpp | Implements Win32 window, DPI handling, theme updates. |
| examples/flutter/RunAnywhereAI/windows/runner/utils.h | Adds Windows runner utility declarations. |
| examples/flutter/RunAnywhereAI/windows/runner/utils.cpp | Implements console attachment and UTF-16→UTF-8 conversion. |
| examples/flutter/RunAnywhereAI/windows/runner/runner.exe.manifest | Adds DPI awareness and supported OS declarations. |
| examples/flutter/RunAnywhereAI/windows/runner/resource.h | Adds runner resources header. |
| examples/flutter/RunAnywhereAI/windows/runner/main.cpp | Adds Windows runner entrypoint. |
| examples/flutter/RunAnywhereAI/windows/runner/flutter_window.h | Declares Flutter host window wrapper. |
| examples/flutter/RunAnywhereAI/windows/runner/flutter_window.cpp | Implements Flutter view controller hosting + message handling. |
| examples/flutter/RunAnywhereAI/windows/runner/Runner.rc | Adds Windows resources (icon/version). |
| examples/flutter/RunAnywhereAI/windows/runner/CMakeLists.txt | Builds Windows runner executable and resources. |
| examples/flutter/RunAnywhereAI/windows/flutter/generated_plugins.cmake | Adds Windows plugin list and bundling logic. |
| examples/flutter/RunAnywhereAI/windows/flutter/generated_plugin_registrant.h | Declares plugin registrant for Windows. |
| examples/flutter/RunAnywhereAI/windows/flutter/generated_plugin_registrant.cc | Registers Windows plugins including runanywhere packages. |
| examples/flutter/RunAnywhereAI/windows/flutter/CMakeLists.txt | Flutter-managed Windows build rules. |
| examples/flutter/RunAnywhereAI/windows/CMakeLists.txt | Top-level Windows build/install rules for example app. |
| examples/flutter/RunAnywhereAI/windows/.gitignore | Ignores Windows ephemeral + VS build artifacts. |
| examples/flutter/RunAnywhereAI/.gitignore | Stops ignoring Windows folder (enables Windows project in repo). |
| examples/flutter/RunAnywhereAI/pubspec.yaml | Pins record version; adds camera_windows dependency. |
| examples/flutter/RunAnywhereAI/test/widget_test.dart | Avoids pumpAndSettle startup timeouts. |
| examples/flutter/RunAnywhereAI/test/features/vision/vlm_view_model_test.dart | Adds extensive tests for new VLM view model behavior and disposal races. |
| examples/flutter/RunAnywhereAI/test/features/vision/vision_camera_backend_test.dart | Tests camera backend error messaging on invalid device handle. |
| examples/flutter/RunAnywhereAI/test/features/dropdown_form_field_compatibility_test.dart | Regression tests for dropdown selector behavior. |
| examples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dart | Tests proxy persistence/legacy migration/validation behavior. |
| examples/flutter/RunAnywhereAI/test/core/services/example_http_service_test.dart | Tests proxy directive building. |
| examples/flutter/RunAnywhereAI/test/core/models/proxy_settings_test.dart | Tests proxy scheme support + copyWith(clearPort) behavior. |
| examples/flutter/RunAnywhereAI/lib/features/voice/voice_assistant_view.dart | Adds capability gating and unsupported-feature UI. |
| examples/flutter/RunAnywhereAI/lib/features/voice/text_to_speech_view.dart | Adds capability gating; refactors model state refresh logic. |
| examples/flutter/RunAnywhereAI/lib/features/voice/speech_to_text_view.dart | Adds capability gating and refreshes model state from SDK. |
| examples/flutter/RunAnywhereAI/lib/features/vision/vlm_view_model.dart | Refactors to injectable camera/permissions/VLM services and improves disposal safety. |
| examples/flutter/RunAnywhereAI/lib/features/vision/vlm_camera_view.dart | Uses new camera session preview; improves error UI; adjusts permission UI copy. |
| examples/flutter/RunAnywhereAI/lib/features/vision/vision_hub_view.dart | Adds capability gating and unsupported-feature UI. |
| examples/flutter/RunAnywhereAI/lib/features/vision/services/vision_vlm_service.dart | Introduces VLM service abstraction around SDK calls. |
| examples/flutter/RunAnywhereAI/lib/features/vision/services/vision_permission_gateway.dart | Introduces permission gateway abstraction for camera. |
| examples/flutter/RunAnywhereAI/lib/features/vision/services/vision_camera_backend.dart | Introduces camera backend/session abstractions and camera plugin adapter. |
| examples/flutter/RunAnywhereAI/lib/features/structured_output/structured_output_view.dart | Fixes dropdown selection to use value rather than initialValue. |
| examples/flutter/RunAnywhereAI/lib/features/settings/tool_settings_view_model.dart | Routes example HTTP calls through proxy-aware HTTP service and improves errors. |
| examples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dart | Adds UI flows to configure/test/clear general and download proxies. |
| examples/flutter/RunAnywhereAI/lib/features/rag/rag_demo_view.dart | Adds capability gating and unsupported-feature UI. |
| examples/flutter/RunAnywhereAI/lib/features/models/model_selection_sheet.dart | Hides System TTS option on Windows. |
| examples/flutter/RunAnywhereAI/lib/features/models/model_list_view_model.dart | Rethrows on load failure (lets callers handle). |
| examples/flutter/RunAnywhereAI/lib/features/models/add_model_from_url_view.dart | Fixes dropdown selection to use value rather than initialValue. |
| examples/flutter/RunAnywhereAI/lib/features/chat/chat_interface_view.dart | Blocks RAG navigation when unsupported and improves logging formatting. |
| examples/flutter/RunAnywhereAI/lib/core/utilities/constants.dart | Adds preference/keychain keys for proxy settings. |
| examples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dart | Implements proxy settings persistence + validation + legacy migration. |
| examples/flutter/RunAnywhereAI/lib/core/services/platform_capability_service.dart | Adds Windows feature gating decisions. |
| examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart | Adds proxy-aware HTTP client creation + JSON GET/test helpers. |
| examples/flutter/RunAnywhereAI/lib/core/models/proxy_settings.dart | Defines proxy settings model/enums and helper methods. |
| examples/flutter/RunAnywhereAI/lib/core/design_system/unsupported_feature_view.dart | Adds reusable unsupported-feature UI component. |
| examples/flutter/RunAnywhereAI/lib/core/design_system/app_colors.dart | Adds color compatibility extension and adjusts grouped background color for compatibility. |
| examples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dart | Configures SDK download client factory to use proxy-aware HTTP client; updates module registration logging. |
| examples/flutter/RunAnywhereAI/ios/Runner/GeneratedPluginRegistrant.m | Updates plugin registrant imports/registration for record + sqflite. |
| examples/flutter/RunAnywhereAI/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java | Updates plugin error log message for sqflite. |
| docs/building.md | Adds Windows build/validation notes for voice + vision in Flutter example. |
| .gitignore | Adds .worktrees/ ignore. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ); | ||
| }, | ||
| child: const Text('Open Settings'), | ||
| child: const Text('Grant Camera Access'), |
There was a problem hiding this comment.
The button label says "Grant Camera Access" but the handler appears to open app settings (not trigger a permission request). This is confusing UX; either change the label back to something like "Open Settings" or update the handler to request permission directly and only fall back to settings when permanently denied.
| child: const Text('Grant Camera Access'), | |
| child: const Text('Open Settings'), |
There was a problem hiding this comment.
Actionable comments posted: 18
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
examples/flutter/RunAnywhereAI/lib/features/models/model_list_view_model.dart (1)
202-212:⚠️ Potential issue | 🔴 CriticalBehavior change:
selectModelnow propagates exceptions — two call sites need review.Previously a load failure was silently swallowed (only
_errorMessageset). Now it rethrows, making unhandled failures surface as zone errors.Verification found:
- ✅
model_selection_sheet.dart:518— properly wrapped in try/catch with error UI (snackbar + state reset)- ❌
models_view.dart:247— in_selectModel()with no error handling. The async callback invoked by ModelRow's button will leave exceptions unhandled whenselectModelrethrows.Add error handling to
_selectModelin models_view.dart (lines 242-248) to catch the exception fromselectModeland show user feedback.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/flutter/RunAnywhereAI/lib/features/models/model_list_view_model.dart` around lines 202 - 212, selectModel now rethrows load errors but _selectModel in models_view.dart (the async callback used by ModelRow's button) doesn't handle them, causing unhandled zone errors; update _selectModel to wrap the await selectModel(...) call in try/catch, set _errorMessage or call the existing error handling UI path (e.g., show a SnackBar or reset state similar to model_selection_sheet.dart), call notifyListeners()/setState as needed, and avoid rethrowing so the UI surface handles the failure gracefully.sdk/runanywhere-commons/src/backends/onnx/CMakeLists.txt (1)
325-334:⚠️ Potential issue | 🔴 CriticalDuplicate
elseif(RAC_PLATFORM_WINDOWS)— the existing Windows branch becomes dead code.The new branch at lines 325-327 is added before the existing
elseif(RAC_PLATFORM_WINDOWS)at line 331, so the original Windows branch will never execute (CMakeelseifevaluates only the first matching condition). Today the only impact is a different status message, but any future Windows-specifictarget_link_libraries/target_compile_optionsplaced in the dead branch will be silently ignored.Either remove the new branch and put the message in the existing Windows branch, or remove the now-dead one.
♻️ Proposed consolidation
elseif(RAC_PLATFORM_MACOS) target_link_libraries(rac_backend_onnx PUBLIC "-framework Foundation" "-framework CoreML" "-framework Accelerate" ) # CoreML Execution Provider is available in ONNX Runtime macOS package target_compile_definitions(rac_backend_onnx PRIVATE ORT_USE_COREML=1) message(STATUS "ONNX Backend: CoreML EP enabled for macOS") -elseif(RAC_PLATFORM_WINDOWS) - message(STATUS "ONNX Backend: Windows build path available when ONNX dependencies are configured") - elseif(RAC_PLATFORM_LINUX) target_link_libraries(rac_backend_onnx PUBLIC pthread dl) elseif(RAC_PLATFORM_WINDOWS) # No extra link libraries needed on Windows - message(STATUS "ONNX Backend: CPU EP for Windows") + message(STATUS "ONNX Backend: CPU EP for Windows (build path available when ONNX dependencies are configured)") endif()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/runanywhere-commons/src/backends/onnx/CMakeLists.txt` around lines 325 - 334, There are two elseif(RAC_PLATFORM_WINDOWS) branches causing the latter to be dead code; open the CMake conditional that contains RAC_PLATFORM_LINUX and both Windows branches and either remove the earlier duplicate elseif(RAC_PLATFORM_WINDOWS) (keeping the existing Windows branch) or merge its message into the surviving elseif(RAC_PLATFORM_WINDOWS); ensure the branch that calls target_link_libraries(rac_backend_onnx PUBLIC pthread dl) remains under RAC_PLATFORM_LINUX and that only one elseif(RAC_PLATFORM_WINDOWS) exists (containing the desired message and any Windows-specific link/compile directives).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@examples/flutter/RunAnywhereAI/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java`:
- Line 106: The change modifies a generated file
(GeneratedPluginRegistrant.java) — revert any manual edits (including the Log.e
line referencing sqflite) and do not commit changes to
GeneratedPluginRegistrant; instead keep plugin config in pubspec.yaml and let
the Flutter tool regenerate the file. If you need persistent custom behavior,
implement plugin registration or error handling in your app entrypoint (e.g.,
MainActivity or a custom registrant) rather than editing
GeneratedPluginRegistrant.java, and ensure GeneratedPluginRegistrant.java is
either kept in sync with pubspec-managed plugins or added to .gitignore if you
intentionally want it out of source control.
In `@examples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dart`:
- Around line 365-378: The log messages in the Onnx.register and
RAGModule.register try/catch blocks hardcode "Windows", which is incorrect for
cross-platform runs; update the messages in the blocks around Onnx.register and
RAGModule.register to be platform-neutral (e.g., remove "Windows" and say
"optional" or "not available on this platform") or use platform detection
(Platform.isX) to insert the actual platform name before logging, ensuring
debugPrint calls reflect the real runtime platform rather than always saying
"Windows".
- Around line 123-128: The download HTTP client factory registration via
RunAnywhere.configureDownloadHttpClientFactory is currently called after
RunAnywhere.initialize(...) and _registerModulesAndModels(), so initial SDK
networking can bypass the proxy; move the configureDownloadHttpClientFactory
call to immediately after RunAnywhere.initialize(...) (or before initialize if
supported) so that all SDK network traffic, including initial metadata/manifest
fetches and lazy bootstrap, uses
ExampleHttpService.shared.createScopedHttpPackageClient(ProxyScope.download,
uri).
In `@examples/flutter/RunAnywhereAI/lib/core/design_system/app_colors.dart`:
- Around line 3-10: Decide the supported minimum Flutter SDK and apply one of
two fixes: if you will keep minimum <3.27 (support 3.10–3.26) keep the backport
extension ColorCompatibility.withValues and usages of Color.withValues and keep
using ColorScheme.surfaceVariant but add clear comments and suppress deprecation
lints for future SDKs; if you raise the minimum to ≥3.27, remove the
ColorCompatibility extension and update all calls to Color.withValues to use the
built-in instance method, and if you raise the minimum to ≥3.22 replace uses of
ColorScheme.surfaceVariant with ColorScheme.surfaceContainerHighest (or the
recommended replacement) across the codebase. Ensure changes reference the
symbols ColorCompatibility.withValues, Color.withValues calls, and
ColorScheme.surfaceVariant so reviewers can find and verify the updates.
In `@examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart`:
- Around line 74-86: The code silently falls back to DIRECT when a user-enabled
proxy is unsupported or _proxyDirectiveForSettings(settings) returns null;
instead, stop the silent fallback and surface a warning/error: in the block that
checks settings.enabled, settings.scheme.isSupportedInExampleApp, and
_shouldUseProxy(settings, targetUri.host) and in the branch where proxyDirective
== null, replace the silent client.findProxy = (_) => 'DIRECT' behavior with a
call to log.warn (or throw an error) indicating the enabled proxy is unsupported
or invalid, include identifying info from settings (e.g., scheme and host), and
ensure callers like testProxy can observe the failure; reference
ProxySettingsService.validate() to keep validation consistent and use
client.findProxy only for explicit DIRECT cases.
In
`@examples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dart`:
- Around line 109-147: The persisted host is trimmed but the in-memory cache
uses the original untrimmed host; update the normalization so the host is
trimmed into normalizedSettings as well (e.g., compute normalizedHost =
settings.host.trim() and pass host: normalizedHost into settings.copyWith when
creating normalizedSettings) so that the value written with _hostKey(scope) and
cached in _current[scope] match exactly; ensure you reference
normalizedUsername, normalizedPassword, normalizedSettings, settings.copyWith,
_hostKey(scope), and _current[scope] when making the change.
In
`@examples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dart`:
- Around line 240-416: The TextEditingController instances created in
_showProxyConfigDialog (hostController, portController, usernameController,
passwordController) are not disposed; wrap the await showDialog(...) call in a
try/finally and call dispose() on each controller in the finally block so they
are cleaned up on every exit path (including Cancel, Save, exceptions), keeping
existing mounted/dialogContext checks intact; locate the controllers and the
showDialog invocation in _showProxyConfigDialog and add the try/finally disposal
there.
In `@examples/flutter/RunAnywhereAI/lib/features/voice/speech_to_text_view.dart`:
- Around line 124-139: _restore the previous null semantics for framework
selection so the UI shows "no model selected" instead of "unknown": in
_refreshModelState(), when currentSTTModel() returns null set _selectedFramework
to null (not LLMFramework.unknown) and leave _selectedModelName null; update any
declaration or initialization of _selectedFramework (used by ModelStatusBanner
and elsewhere) to be nullable if it was made non-nullable so the UI branches
that check for null continue to work; ensure the switch branch still maps
sdk.InferenceFramework.onnx to LLMFramework.onnxRuntime when a model exists.
- Line 136: The code unconditionally sets _supportsLiveMode = false in the
refresh path, which forces the Live UI to fall back to batch; instead, derive
live capability from the selected model or hide the Live UI. Update the refresh
logic that sets _supportsLiveMode to consult currentSTTModel() (or add a
capability flag on ModelInfo) and set _supportsLiveMode = model.supportsLive (or
similar), and then conditionally render/disable the Live segment UI when
_supportsLiveMode is false so the UI accurately reflects whether Live
transcription is available.
In `@examples/flutter/RunAnywhereAI/lib/features/voice/voice_assistant_view.dart`:
- Around line 319-330: The initState method must gate initialization on the
platform capability: in initState() (in this StatefulWidget) call
super.initState(), then fetch PlatformCapabilityService.shared and if
supportsVoiceAssistant is false skip the voice-related setup (do not create the
animation controller or call _refreshComponentStates()); otherwise proceed with
the existing initialization. This prevents touching SDK getters (currentModelId,
currentSTTModelId, currentTTSVoiceId) or creating controllers when the feature
is unsupported.
In `@examples/flutter/RunAnywhereAI/pubspec.yaml`:
- Line 30: The pubspec change pins `record` to 5.2.0 but your code uses the
post-6.0 class name AudioRecorder (found in audio_recording_service.dart and
audio_capture_manager.dart) and APIs like RecordConfig, startStream(), and
hasPermission(); this will fail to compile. Fix by either updating the
dependency back to a 6.x release (e.g., ^6.1.0) so AudioRecorder and its APIs
remain available, or refactor all AudioRecorder usages to the older Record class
and verify/adjust calls to RecordConfig, startStream(), and hasPermission() to
match the 5.2.0 API surface. Ensure all instantiations and imports for
AudioRecorder/Record are consistently updated across the codebase.
In `@examples/flutter/RunAnywhereAI/test/core/models/proxy_settings_test.dart`:
- Around line 5-9: The test name is misleading because it mentions "while
disabled" but only checks the static ProxyScheme.supportedValues; either rename
the test to remove "while disabled" or update it to construct a disabled
ProxySettings instance (e.g., new ProxySettings(enabled: false) or whatever the
constructor/method is) and assert that that instance's effectiveScheme
list/exposed supported schemes excludes ProxyScheme.socks5 while still including
ProxyScheme.http and ProxyScheme.https; locate references to
ProxyScheme.supportedValues, ProxyScheme.socks5, and the ProxySettings
constructor/field in the test file and adjust the test name or add the
disabled-state assertions accordingly.
In
`@examples/flutter/RunAnywhereAI/test/core/services/example_http_service_test.dart`:
- Around line 20-29: The test description contradicts its data: the test named
"does not build a proxy directive for SOCKS5 while disabled" sets
ProxySettings(enabled: true) but asserts
ExampleHttpService.proxyDirectiveForTesting returns null; fix by renaming the
test to reflect the actual scenario (e.g., "does not build a proxy directive for
SOCKS5") or change the ProxySettings to enabled: false if you intended to test
the disabled path, and optionally add a separate test that explicitly covers the
disabled case using ProxySettings(enabled: false) to avoid future confusion.
In `@examples/flutter/RunAnywhereAI/test/widget_test.dart`:
- Around line 13-16: Replace the fixed 300 ms pump with a bounded polling loop
that repeatedly calls tester.pump() (or tester.pump(const Duration(...)) between
iterations) until the expected widget is present or a max duration elapses;
update the test that currently uses tester.pump(); and tester.pump(const
Duration(milliseconds: 300)); to poll for the target widget (e.g., by checking
find.byType/find.text) with a short sleep interval and a clear timeout to avoid
flakes on slow CI while keeping the avoidance of pumpAndSettle.
In `@sdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cpp`:
- Around line 649-654: In rac_backend_onnx_unregister(), the variable result is
used inside the RAC_ONNX_EMBEDDINGS_AVAILABLE block but never declared; declare
a local rac_result_t result (same type used in rac_backend_onnx_register())
before using it so the call to rac_backend_onnx_embeddings_unregister() can
assign to it and the subsequent checks against RAC_SUCCESS and
RAC_ERROR_MODULE_NOT_FOUND work correctly; update the scope so result is visible
to the embedding-unregister branch.
In
`@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp`:
- Around line 234-258: The Windows implementation of find_single_model_file
currently interleaves recursion while iterating
std::filesystem::directory_iterator, allowing a deeper model to be chosen before
checking all same-level files; change the Windows branch to a two-pass scan to
match the POSIX behavior: first iterate directory_iterator collecting/inspecting
all entries and immediately return if a non-auxiliary model file is found (use
is_model_extension and is_auxiliary_model_file to identify valid files), then in
a second pass recurse into collected subdirectories (calling
find_single_model_file for each) and only return a deeper result if no
same-level file was chosen; keep error_code usage and out_path/path_size
handling identical.
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dart`:
- Around line 26-36: The progress calc currently returns 0 when totalModelBytes
<= 0, causing multi-file downloads with no aggregate size to stall; update
_calculateOverallMultiFileDownloadProgress to fall back to an index-based
estimate when totalModelBytes <= 0 by taking (filesCompleted +
currentFileFraction) / totalFiles, where filesCompleted and totalFiles are
provided (or derive them from the download context) and currentFileFraction =
downloadedBytesForCurrentFile / max(1, currentFileSizeEstimate); clamp the
result as before. Also adjust the progress emission (where bytesDownloaded =
cumulativeDownloaded + downloaded and totalBytes = totalModelBytes) to avoid
emitting totalBytes=0 — when aggregate size is unknown either emit totalBytes as
null/omitted or set totalBytes to cumulativeDownloaded (so consumers can show
indeterminate/relative progress) and ensure callers of
_calculateOverallMultiFileDownloadProgress pass the new file-index/total-file
parameters (or compute them before calling).
In `@sdk/runanywhere-flutter/packages/runanywhere/windows/CMakeLists.txt`:
- Around line 57-66: The current post-build step only copies a single
COMMONS_DLL into the plugin output, which misses other DLLs in the commons dist
(e.g., rac_backend_*.dll and ONNX/Sherpa DLLs) and breaks Windows dependency
resolution; update the CMake logic around PLUGIN_NAME and
runanywhere_bundled_libraries to glob all DLLs from the commons dist directory
(instead of using the single COMMONS_DLL), then iterate the list and add a
post-build copy command for each DLL into $<TARGET_FILE_DIR:${PLUGIN_NAME}> so
all transitive DLLs are staged alongside rac_commons.dll and included in
runanywhere_bundled_libraries.
---
Outside diff comments:
In
`@examples/flutter/RunAnywhereAI/lib/features/models/model_list_view_model.dart`:
- Around line 202-212: selectModel now rethrows load errors but _selectModel in
models_view.dart (the async callback used by ModelRow's button) doesn't handle
them, causing unhandled zone errors; update _selectModel to wrap the await
selectModel(...) call in try/catch, set _errorMessage or call the existing error
handling UI path (e.g., show a SnackBar or reset state similar to
model_selection_sheet.dart), call notifyListeners()/setState as needed, and
avoid rethrowing so the UI surface handles the failure gracefully.
In `@sdk/runanywhere-commons/src/backends/onnx/CMakeLists.txt`:
- Around line 325-334: There are two elseif(RAC_PLATFORM_WINDOWS) branches
causing the latter to be dead code; open the CMake conditional that contains
RAC_PLATFORM_LINUX and both Windows branches and either remove the earlier
duplicate elseif(RAC_PLATFORM_WINDOWS) (keeping the existing Windows branch) or
merge its message into the surviving elseif(RAC_PLATFORM_WINDOWS); ensure the
branch that calls target_link_libraries(rac_backend_onnx PUBLIC pthread dl)
remains under RAC_PLATFORM_LINUX and that only one elseif(RAC_PLATFORM_WINDOWS)
exists (containing the desired message and any Windows-specific link/compile
directives).
---
Nitpick comments:
In
`@examples/flutter/RunAnywhereAI/lib/core/design_system/unsupported_feature_view.dart`:
- Line 22: Replace the hardcoded icon size in the unsupported feature view with
the design token from AppSpacing: find the const Icon(Icons.info_outline, size:
40) in unsupported_feature_view.dart and change it to use the corresponding
AppSpacing constant (e.g. AppSpacing.iconXXLarge) so the icon sizing matches the
rest of the app (see _buildResults usage in structured_output_view.dart for the
matching token).
In `@examples/flutter/RunAnywhereAI/lib/core/models/proxy_settings.dart`:
- Around line 57-76: The copyWith currently uses a boolean clearPort to
distinguish clearing port vs leaving it; replace this with a sentinel-based
pattern so callers can pass a special value to mean "clear" while null means
"leave unchanged." Add a private static sentinel (e.g., _portSentinel =
Object()), change the copyWith signature to accept Object? port = _portSentinel
(or dynamic port = _portSentinel) instead of int? and remove clearPort; inside
ProxySettings.copyWith check for identical(port, _portSentinel) to keep
this.port, check for port == null to clear the port (set to null), otherwise
cast to int and use the provided value; update callers to use null to clear and
omit the parameter to keep existing port.
In `@examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart`:
- Around line 27-44: The getJson method assumes UTF-8 when decoding the response
which can throw FormatException for non-UTF8 or binary bodies; update getJson
(in ExampleHttpService) to inspect response.headers.contentType?.charset (or
default to 'utf-8'), attempt to decode with the specified charset using
utf8.decode but guard with a try/catch for FormatException, and on decode
failure fall back to latin1.decode (or a lenient path) so you always return an
ExampleHttpResponse with the response.statusCode and a string body; ensure the
client.close(force: true) in the finally remains and convert any caught decode
errors into a safe string body rather than letting exceptions escape.
- Around line 66-107: createScopedHttpClient currently only sets
HttpClient.connectionTimeout (affects TCP connect) so long-running/stalled
responses can hang; set client.idleTimeout to a reasonable Duration (e.g., 30s)
inside createScopedHttpClient after connectionTimeout, and update callers that
perform request.close()/body reads (notably testProxy and getJson) to wrap their
request/response futures in Future.timeout(...) to bound total wall time and
handle TimeoutException; ensure the combined timeouts (connectionTimeout +
idleTimeout + caller timeout) provide the desired overall budget and surface
clear error handling when a timeout occurs.
- Around line 114-123: The _shouldUseProxy function currently treats
ProxySettings.bypassLocal as bypassing only loopback; update it to implement
common "bypass local network" semantics instead of renaming: detect if the host
is an IP and check RFC1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
and IPv6 link-local (fe80::/10) and loopback (::1, 127.0.0.0/8), and if the host
is a hostname treat single-label names (no dot), names ending with ".local", and
literal hostnames that resolve to private addresses as local; return false (do
not use proxy) for these cases and true otherwise; use existing function
_shouldUseProxy and the ProxySettings.bypassLocal flag as the toggle, and add a
small helper (e.g., isPrivateIp or isLocalHostname) to keep logic readable.
In
`@examples/flutter/RunAnywhereAI/lib/core/services/platform_capability_service.dart`:
- Around line 18-19: The UI helper unsupportedMessage currently hardcodes
"Windows vertical-slice" which leaks build gating into user-facing text; update
the unsupportedMessage(String featureName) implementation in
platform_capability_service.dart to return a neutral or platform-aware message
(e.g., "$featureName is not available on this platform yet." or use Dart's
Platform.operatingSystem to inject the actual OS name). Ensure callers like
supportsRag, supportsVision, supportsSpeechToText continue to call
unsupportedMessage and receive the corrected, non-Windows-specific message.
In
`@examples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dart`:
- Around line 29-62: When load(ProxyScope scope) detects scope ==
ProxyScope.general and no scoped prefs exist, read legacy settings via
_loadLegacyGeneralSettings as now but then migrate them by writing the
equivalent scoped keys (use the same logic as save()) into SharedPreferences and
KeychainHelper (set username/password) and remove the legacy keys so future cold
starts see only scoped prefs; update _current[scope] with the migrated
ProxySettings and ensure migration happens only once (e.g., after successful
write) to avoid duplicating writes.
In `@examples/flutter/RunAnywhereAI/lib/features/chat/chat_interface_view.dart`:
- Around line 462-488: The IconButton's onPressed currently uses an async IIFE
inside unawaited which reduces readability; extract a helper method (e.g.,
_openRagDemo) that captures PlatformCapabilityService.shared, checks
supportsRag, shows the SnackBar via ScaffoldMessenger.of(context) with
unsupportedMessage('Document Q&A') and otherwise calls
unawaited(Navigator.of(context).push(MaterialPageRoute(builder: (_) => const
RagDemoView()))); then set IconButton.onPressed to call that helper to keep the
button declarative and make the capability gate easier to scan.
In
`@examples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dart`:
- Around line 141-169: The code stores proxy scheme as a String (fields
_generalProxyScheme and _downloadProxyScheme) but should keep the enum
ProxyScheme for type safety; in _loadProxyConfiguration(ProxyScope) assign
selectedScheme (a ProxyScheme) directly to those fields (change their types from
String to ProxyScheme) and update any UI/display sites that currently call
.toUpperCase() or expect a wireValue to use selectedScheme.wireValue or
selectedScheme.name/enum-to-string conversion at the presentation layer instead;
update usages (e.g., where _generalProxyScheme/_downloadProxyScheme are read,
such as the display at line ~1075) to call the enum’s wireValue or name when a
string is needed.
- Around line 428-450: The proxy test currently hardcodes the external endpoint
in _testProxyConfiguration (uses ExampleHttpService.shared.testProxy with
Uri.parse('https://api.ipify.org?format=json')), which exposes the user’s egress
IP; make the test target configurable or document it in the UI by adding a
settings field and UI hint. Update the settings view to surface a “Proxy test
URL” input (defaulting to https://api.ipify.org?format=json) and validate the
entered string as a URI, then pass that URI into
ExampleHttpService.shared.testProxy instead of the hardcoded value;
alternatively, add a short notice near the test button showing that the check
will send one request to the configured host. Ensure changes reference
_testProxyConfiguration, ProxyScope, and ExampleHttpService.shared.testProxy so
the code paths are updated and validated.
In `@examples/flutter/RunAnywhereAI/lib/features/vision/vlm_camera_view.dart`:
- Around line 351-363: The current code wraps showSnackBar in unawaited and adds
`.then((_) => null)` to coerce the returned Future type; simplify by removing
the unnecessary unawaited and the `.then(...)` coercion: call
ScaffoldMessenger.of(context).showSnackBar(...) directly (and keep the existing
SnackBar content), or if you intend to observe when it closes use the returned
controller's `.closed` Future and call unawaited on that instead; refer to
Clipboard.setData, _viewModel.currentDescription,
ScaffoldMessenger.of(context).showSnackBar, and the SnackBarController.closed
symbol to locate the lines to change.
In `@examples/flutter/RunAnywhereAI/lib/features/voice/speech_to_text_view.dart`:
- Line 64: The _isProcessing field is incorrectly declared final and set to
false, making all guards like isLoading: _isProcessing && ..., if
(!_hasModelSelected && !_isProcessing), ! _isProcessing && !_isTranscribing &&
_hasModelSelected, and _isProcessing || _isTranscribing constant; either make
_isProcessing a mutable state boolean and toggle it around the model-load
lifecycle (set _isProcessing = true before starting model load in the method
that initiates loading and set to false in the completion/error handlers,
calling setState()), or remove the field and simplify those expressions to rely
on _isTranscribing/_hasModelSelected alone (update UI props such as isLoading
accordingly) so the logic no longer depends on a permanently false flag; update
all references to _isProcessing, including the UI isLoading uses and
conditionals that gate model selection and transcribing UI.
In `@sdk/runanywhere-commons/CMakeLists.txt`:
- Around line 33-34: Rename the new CMake option RAC_BUILD_VLM to follow the
per-backend naming convention (e.g., RAC_BACKEND_LLAMACPP_VLM), update all
usages that read the variable in the llama.cpp backend CMake (the variable
referenced in sdk/runanywhere-commons/src/backends/llamacpp/CMakeLists.txt), and
replace references to the old name (RAC_BUILD_VLM) throughout the repo; also add
a line to the configuration-summary block alongside the other backend status
lines so the VLM flag is visible in the build summary.
In `@sdk/runanywhere-commons/README.md`:
- Around line 278-281: The artifact list currently under the "Windows ONNX
Dependencies" heading incorrectly mixes ONNX and non-ONNX outputs (e.g.,
rac_commons.dll and rac_backend_llamacpp.dll); move that list out of the ONNX
section and either (a) place it above the "Windows ONNX Dependencies" header or
(b) create a dedicated "Artifacts" subsection in README.md that lists
`dist/windows/x64/rac_commons.dll` and
`dist/windows/x64/rac_backend_llamacpp.dll`, and update any references (e.g.,
mention of build-windows.bat onnx) so readers won’t assume
rac_backend_llamacpp.dll is produced by the onnx build.
In `@sdk/runanywhere-commons/scripts/build-windows.bat`:
- Around line 4-30: The argument parsing currently lets later backend options
overwrite earlier ones (BACKENDS) silently; update the :parse_args logic (around
the BACKENDS, ARG_MATCHED, and CLEAN handling) to detect when a backend flag is
provided after a different backend has already been set and either (a) reject
the duplicate by printing a clear error/warning and jump to usage_error, or (b)
print a one-line note about precedence and keep the first/last choice per
project policy; implement this by checking BACKENDS against its default
("llamacpp") or adding a flag like ARG_BACKENDS_SET when you first set BACKENDS
in the parse_args block and use that to decide whether to error/notify, ensuring
--clean, -h/--help and existing goto usage/usage_error flows remain unchanged.
In `@sdk/runanywhere-commons/scripts/windows/download-sherpa-onnx.bat`:
- Around line 132-140: The summary currently lists DLLs from
"%DEST_DIR%\lib\*.dll" which can miss or duplicate sherpa-onnx-c-api.dll after
normalization; update the summary block in download-sherpa-onnx.bat (the echo
"Libraries" / dir commands using %DEST_DIR%) to also list DLLs from
"%DEST_DIR%\bin\*.dll" (or replace the lib\*.dll listing with bin\*.dll) so the
final output reflects the canonical layout; ensure you keep the existing
lib\*.lib and include both locations or prefer bin for DLL enumeration to avoid
missing files.
In `@sdk/runanywhere-commons/src/backends/llamacpp/CMakeLists.txt`:
- Around line 273-276: The CMake target_link_libraries call currently exposes
ws2_32 as PUBLIC for rac_backend_llamacpp; if Winsock is only used internally by
the backend (not in public headers), change that linkage to PRIVATE so consumers
aren't forced to link Winsock transitively. Locate the
target_link_libraries(rac_backend_llamacpp PUBLIC ws2_32) line and replace
PUBLIC with PRIVATE (keep target_compile_definitions for NOMINMAX
WIN32_LEAN_AND_MEAN as-is); only leave PUBLIC if a public header of
rac_backend_llamacpp requires Winsock symbols.
In `@sdk/runanywhere-commons/src/backends/onnx/onnx_backend.cpp`:
- Around line 864-876: The diagnostic loop uses stat(diag_path.c_str(),
&diag_stat) to set is_dir and currently treats stat failures as files; update
the loop around diag_entry/stat/is_dir to detect when stat() fails and surface
that via RAC_LOG_INFO (e.g., log errno/strerror and mark entry as "STAT_ERR" or
similar) instead of silently labeling it "FILE"; refer to diag_entry, diag_path,
stat, is_dir and the RAC_LOG_INFO call so you add a branch that logs the stat
failure details before continuing and then still calls closedir(diag_dir) as
before.
In `@sdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cpp`:
- Around line 626-640: The code mixes compile-time and runtime uses of
RAC_ONNX_EMBEDDINGS_AVAILABLE which can break builds if the macro is undefined;
update the ONNX backend registration to avoid using
RAC_ONNX_EMBEDDINGS_AVAILABLE in a runtime expression: keep the existing
`#if/`#endif around the call to rac_backend_onnx_embeddings_register() and change
the RAC_LOG_INFO call to use a compile-time branch (e.g., wrap the log message
in `#if` RAC_ONNX_EMBEDDINGS_AVAILABLE / `#else` / `#endif`) so the string literal
includes " + Embeddings" only when the macro is defined, referencing the
existing symbols rac_backend_onnx_embeddings_register, RAC_LOG_INFO, LOG_CAT and
g_registered.
In `@sdk/runanywhere-commons/src/core/rac_core.cpp`:
- Around line 21-23: Create a single Apple-platform macro and use it where the
predicate is repeated: add a definition like RAC_PLATFORM_APPLE in the platform
header (e.g., rac/core/rac_platform.h) that expands to
(defined(RAC_PLATFORM_IOS) || defined(RAC_PLATFORM_MACOS)), then replace each
occurrence of the explicit predicate in this file (the preprocessor guards
around includes and feature code such as the current include of
"rac/features/diffusion/rac_diffusion_model_registry.h" in rac_core.cpp and the
other two similar guards) with the new RAC_PLATFORM_APPLE macro so the intent is
self-documenting and future changes require updating one place.
In
`@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp`:
- Around line 365-382: The readdir loop calls stat(full_path.c_str(), &st) twice
for each entry; change it to call stat once and branch on st.st_mode: after
building full_path and declaring struct stat st, call stat(full_path.c_str(),
&st) once, check the return value == 0, then use if (S_ISDIR(st.st_mode)) {
visible_dirs.push_back(full_path); } else if (S_ISREG(st.st_mode)) {
has_visible_files = true; } and remove the duplicated stat calls; keep the same
skips for "."/".." and hidden/._ entries and preserve the variables entry,
full_path, visible_dirs and has_visible_files.
In
`@sdk/runanywhere-commons/src/infrastructure/extraction/rac_extraction_stub.cpp`:
- Around line 23-25: The stub currently assigns a fixed four-element brace list
to *out_result which ties it to the struct's current layout; replace the
explicit list with value‑initialization so all fields are zeroed regardless of
future changes: where the code does "*out_result = {0, 0, 0, 0};" update it to
"*out_result = {};" (keeping the existing null check on out_result) and
reference the rac_extraction_result_t instance via out_result to ensure correct,
layout-independent initialization.
In
`@sdk/runanywhere-flutter/packages/runanywhere_llamacpp/lib/native/llamacpp_bindings.dart`:
- Around line 53-93: Update the doc comment for loadBackendLibrary to include a
note about the Windows code path (e.g., mention that on Windows it loads
rac_backend_llamacpp via PlatformLoader.loadLibrary), and wrap the Windows
PlatformLoader.loadCommons() +
PlatformLoader.loadLibrary('rac_backend_llamacpp') calls in a try/catch that
catches any error from loadCommons or loadLibrary and rethrows a new,
descriptive error (or ArgumentError) that explains the missing dependency
relationship (e.g., "Could not load LlamaCpp backend on Windows; ensure commons
library loaded: <original error>"). Reference loadBackendLibrary,
PlatformLoader.loadCommons, and PlatformLoader.loadLibrary when making the
changes.
In
`@sdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/CMakeLists.txt`:
- Around line 49-53: Update the FATAL_ERROR message that checks
LLAMA_BACKEND_DLL to give actionable build instructions: include the specific
build target names ("llamacpp" or "all") to pass to scripts/build-windows.bat
and mention the expected output path using the LLAMA_BACKEND_DLL variable (and
optionally reference LLAMA_BACKEND_DLL_CANDIDATES) so the error tells the
developer exactly which target to run and which DLL path to expect.
In
`@sdk/runanywhere-flutter/packages/runanywhere_onnx/lib/native/onnx_bindings.dart`:
- Around line 51-56: Update the docstring above the static ONNX backend loader
(the "Load the ONNX backend library." comment used by the static method called
from Onnx.isAvailable) to include a one-line mention of the Windows behavior:
state that when Platform.isWindows the code loads rac_backend_onnx after commons
(or the equivalent Windows DLL name), in addition to the existing iOS/macOS and
Android notes so readers know Windows is handled.
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/internal/vlm_file_resolution.dart`:
- Around line 23-31: The selection of the "main" .gguf is non-deterministic
because filePaths/dir.list() order is undefined; update the code that builds
ggufPaths/mainModelPaths (referencing ggufPaths, mainModelPaths and
vlmPathBasename) to sort the candidate list deterministically (for example sort
by vlmPathBasename(path).toLowerCase() or full path lexicographically) before
returning .first so the same file is chosen across runs/platforms.
- Around line 8-13: The vlmPathBasename function uses a backslash substring to
choose Windows vs POSIX parsing which misparses valid POSIX filenames containing
'\'—change the heuristic to use Platform.isWindows instead: in vlmPathBasename,
replace the path.contains(r'\') check with a runtime OS check
(Platform.isWindows) and construct p.Context(style: p.Style.windows) or
p.Style.posix accordingly so basename(path) is computed with the correct
platform semantics; reference vlmPathBasename and the p.Context/p.Style usage
when making the change.
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_auth.dart`:
- Around line 25-44: The function _copyUtf8StringToBuffer should explicitly
guard against non-positive bufferSize to avoid relying on negative maxLen
behavior; update _copyUtf8StringToBuffer to check if bufferSize <= 0 at the top
and return -1 immediately, then proceed as before (compute maxLen = bufferSize -
1, check bytes.length > maxLen, copy bytes into outValue.cast<Uint8>(), and
write the null terminator) so the intent is clear and hardened against buggy
native callers.
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_model_registry.dart`:
- Around line 846-849: Replace the manual path manipulation in the entries
computation with package:path's basename to handle platform edge cases: import
'package:path/path.dart' as p, then when mapping over dir.listSync() use
p.basename(e.path) instead of replaceAll(...).split(...).last so the entries
list is produced reliably across platforms (reference the entries variable and
the dir.listSync() mapping).
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/native/platform_loader.dart`:
- Around line 236-254: The Windows loader in _loadWindows currently only tries
the executableDir path and then throws; restore minimal fallbacks by trying
DynamicLibrary.open with the bare dllName and with a relative './$dllName' (or
current working directory) after the absolute executableDir attempt so tests and
dev builds can resolve via PATH/CWD; update the paths/attempt order in
_loadWindows to try: executableDir\<dllName>, './<dllName>', then '<dllName>'
and include these attempts in the loop that calls
DynamicLibrary.open(libraryPath) and only throw the ArgumentError after all
three attempts fail.
In
`@sdk/runanywhere-flutter/packages/runanywhere/test/auth_sdk_config_ffi_layout_test.dart`:
- Around line 9-14: The test currently only compares
sizeOf<auth_bridge.RacSdkConfigStruct>() to
sizeOf<environment_bridge.RacSdkConfigStruct>(), which misses field-order/type
drift; update the test to assert per-field offsets by using
offsetOf<FieldName>() (e.g. offsetOf<Int32>('someField')) for every member on
both types and expect them to be equal, or alternatively import/re-export a
single canonical struct definition so both modules use the exact same
RacSdkConfigStruct; locate the assertions in
auth_sdk_config_ffi_layout_test.dart and add offsetOf-based checks for each
struct field in auth_bridge.RacSdkConfigStruct and
environment_bridge.RacSdkConfigStruct (or replace with a single shared struct
re-export).
In
`@sdk/runanywhere-flutter/packages/runanywhere/test/dart_bridge_auth_test.dart`:
- Around line 60-61: The current assertions on requestMetadata and
responseMetadata only check for exact-string equality; update the checks so they
assert no metadata string value contains the sensitive substrings. Replace the
two lines using expect(requestMetadata.values, isNot(contains(requestJson))) and
expect(responseMetadata.values, isNot(contains(response.body))) with logic that
iterates over requestMetadata.values and responseMetadata.values, converts each
value to a string (e.g., v.toString()), and asserts that none
.contains(requestJson) or .contains(response.body) (or their sensitive
substrings) — use requestMetadata and responseMetadata variable names to locate
code and keep the rest of the test unchanged.
In
`@sdk/runanywhere-flutter/packages/runanywhere/test/download_service_test.dart`:
- Around line 1-60: Change the "multi-file download progress uses zero when
total model size is unknown" test to assert using a double-tolerant matcher like
closeTo(0.0, 0.0001) instead of the integer 0 so the expectation matches the
return type of calculateOverallMultiFileDownloadProgressForTesting and follows
the style used elsewhere in this file.
In `@sdk/runanywhere-flutter/packages/runanywhere/windows/CMakeLists.txt`:
- Around line 35-55: The DLL lookup is brittle because REPO_ROOT_FROM_APP
assumes a fixed 4-level layout; update the CMake logic in CMakeLists.txt to
first honor an explicit override and then fall back to existing candidates: add
a cache variable (e.g. RAC_COMMONS_DLL) that can be set via
-DRAC_COMMONS_DLL=... or an environment variable and check it before populating
COMMONS_DLL_CANDIDATES, then if RAC_COMMONS_DLL is set validate EXISTS and set
COMMONS_DLL to it; otherwise keep the current population of
COMMONS_DLL_CANDIDATES and the foreach that sets COMMONS_DLL, and update the
FATAL_ERROR message to include the attempted override value for easier debugging
(referencing REPO_ROOT_FROM_APP, COMMONS_DLL_CANDIDATES, COMMONS_DLL and the new
RAC_COMMONS_DLL cache variable).
In `@sdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin.cpp`:
- Around line 51-54: The Windows plugin currently returns hardcoded strings in
runanywhere_plugin.cpp for the methods getSDKVersion and getCommonsVersion;
replace those literals by using compile-time defines injected from CMake (e.g.,
RAC_FLUTTER_SDK_VERSION and RAC_COMMONS_VERSION) so the values come from the
single source-of-truth. Update windows/CMakeLists.txt to add
target_compile_definitions for RAC_FLUTTER_SDK_VERSION and RAC_COMMONS_VERSION
(using your PROJECT_VERSION/COMMONS_VERSION variables), then change the handlers
for method_name().compare("getSDKVersion") and
method_name().compare("getCommonsVersion") to return the corresponding
compile-time constants instead of the hardcoded "0.16.0"/"0.1.5".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d419315c-cc6d-4f57-847c-125954dcebd4
⛔ Files ignored due to path filters (1)
examples/flutter/RunAnywhereAI/windows/runner/resources/app_icon.icois excluded by!**/*.ico
📒 Files selected for processing (100)
.gitignoredocs/building.mdexamples/flutter/RunAnywhereAI/.gitignoreexamples/flutter/RunAnywhereAI/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.javaexamples/flutter/RunAnywhereAI/ios/Runner/GeneratedPluginRegistrant.mexamples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dartexamples/flutter/RunAnywhereAI/lib/core/design_system/app_colors.dartexamples/flutter/RunAnywhereAI/lib/core/design_system/unsupported_feature_view.dartexamples/flutter/RunAnywhereAI/lib/core/models/proxy_settings.dartexamples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dartexamples/flutter/RunAnywhereAI/lib/core/services/platform_capability_service.dartexamples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dartexamples/flutter/RunAnywhereAI/lib/core/utilities/constants.dartexamples/flutter/RunAnywhereAI/lib/features/chat/chat_interface_view.dartexamples/flutter/RunAnywhereAI/lib/features/models/add_model_from_url_view.dartexamples/flutter/RunAnywhereAI/lib/features/models/model_list_view_model.dartexamples/flutter/RunAnywhereAI/lib/features/models/model_selection_sheet.dartexamples/flutter/RunAnywhereAI/lib/features/rag/rag_demo_view.dartexamples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dartexamples/flutter/RunAnywhereAI/lib/features/settings/tool_settings_view_model.dartexamples/flutter/RunAnywhereAI/lib/features/structured_output/structured_output_view.dartexamples/flutter/RunAnywhereAI/lib/features/vision/services/vision_camera_backend.dartexamples/flutter/RunAnywhereAI/lib/features/vision/services/vision_permission_gateway.dartexamples/flutter/RunAnywhereAI/lib/features/vision/services/vision_vlm_service.dartexamples/flutter/RunAnywhereAI/lib/features/vision/vision_hub_view.dartexamples/flutter/RunAnywhereAI/lib/features/vision/vlm_camera_view.dartexamples/flutter/RunAnywhereAI/lib/features/vision/vlm_view_model.dartexamples/flutter/RunAnywhereAI/lib/features/voice/speech_to_text_view.dartexamples/flutter/RunAnywhereAI/lib/features/voice/text_to_speech_view.dartexamples/flutter/RunAnywhereAI/lib/features/voice/voice_assistant_view.dartexamples/flutter/RunAnywhereAI/pubspec.yamlexamples/flutter/RunAnywhereAI/test/core/models/proxy_settings_test.dartexamples/flutter/RunAnywhereAI/test/core/services/example_http_service_test.dartexamples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dartexamples/flutter/RunAnywhereAI/test/features/dropdown_form_field_compatibility_test.dartexamples/flutter/RunAnywhereAI/test/features/vision/vision_camera_backend_test.dartexamples/flutter/RunAnywhereAI/test/features/vision/vlm_view_model_test.dartexamples/flutter/RunAnywhereAI/test/widget_test.dartexamples/flutter/RunAnywhereAI/windows/.gitignoreexamples/flutter/RunAnywhereAI/windows/CMakeLists.txtexamples/flutter/RunAnywhereAI/windows/flutter/CMakeLists.txtexamples/flutter/RunAnywhereAI/windows/flutter/generated_plugin_registrant.ccexamples/flutter/RunAnywhereAI/windows/flutter/generated_plugin_registrant.hexamples/flutter/RunAnywhereAI/windows/flutter/generated_plugins.cmakeexamples/flutter/RunAnywhereAI/windows/runner/CMakeLists.txtexamples/flutter/RunAnywhereAI/windows/runner/Runner.rcexamples/flutter/RunAnywhereAI/windows/runner/flutter_window.cppexamples/flutter/RunAnywhereAI/windows/runner/flutter_window.hexamples/flutter/RunAnywhereAI/windows/runner/main.cppexamples/flutter/RunAnywhereAI/windows/runner/resource.hexamples/flutter/RunAnywhereAI/windows/runner/runner.exe.manifestexamples/flutter/RunAnywhereAI/windows/runner/utils.cppexamples/flutter/RunAnywhereAI/windows/runner/utils.hexamples/flutter/RunAnywhereAI/windows/runner/win32_window.cppexamples/flutter/RunAnywhereAI/windows/runner/win32_window.hsdk/runanywhere-commons/CMakeLists.txtsdk/runanywhere-commons/README.mdsdk/runanywhere-commons/scripts/build-windows.batsdk/runanywhere-commons/scripts/windows/download-sherpa-onnx.batsdk/runanywhere-commons/src/backends/llamacpp/CMakeLists.txtsdk/runanywhere-commons/src/backends/onnx/CMakeLists.txtsdk/runanywhere-commons/src/backends/onnx/onnx_backend.cppsdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cppsdk/runanywhere-commons/src/core/rac_core.cppsdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cppsdk/runanywhere-commons/src/infrastructure/extraction/rac_extraction_stub.cppsdk/runanywhere-commons/tests/test_download_orchestrator.cppsdk/runanywhere-flutter/packages/runanywhere/README.mdsdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dartsdk/runanywhere-flutter/packages/runanywhere/lib/internal/vlm_file_resolution.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_auth.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_model_registry.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_stt.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/dart_bridge_tts.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/platform_loader.dartsdk/runanywhere-flutter/packages/runanywhere/lib/public/runanywhere.dartsdk/runanywhere-flutter/packages/runanywhere/pubspec.yamlsdk/runanywhere-flutter/packages/runanywhere/test/auth_sdk_config_ffi_layout_test.dartsdk/runanywhere-flutter/packages/runanywhere/test/dart_bridge_auth_test.dartsdk/runanywhere-flutter/packages/runanywhere/test/download_service_test.dartsdk/runanywhere-flutter/packages/runanywhere/test/vlm_file_resolution_test.dartsdk/runanywhere-flutter/packages/runanywhere/windows/CMakeLists.txtsdk/runanywhere-flutter/packages/runanywhere/windows/include/runanywhere/runanywhere_plugin_c_api.hsdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin.cppsdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin.hsdk/runanywhere-flutter/packages/runanywhere/windows/runanywhere_plugin_c_api.cppsdk/runanywhere-flutter/packages/runanywhere_llamacpp/lib/native/llamacpp_bindings.dartsdk/runanywhere-flutter/packages/runanywhere_llamacpp/pubspec.yamlsdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/CMakeLists.txtsdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/include/runanywhere_llamacpp/runanywhere_llamacpp_plugin_c_api.hsdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin.cppsdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin.hsdk/runanywhere-flutter/packages/runanywhere_llamacpp/windows/runanywhere_llamacpp_plugin_c_api.cppsdk/runanywhere-flutter/packages/runanywhere_onnx/lib/native/onnx_bindings.dartsdk/runanywhere-flutter/packages/runanywhere_onnx/pubspec.yamlsdk/runanywhere-flutter/packages/runanywhere_onnx/windows/CMakeLists.txtsdk/runanywhere-flutter/packages/runanywhere_onnx/windows/include/runanywhere_onnx/runanywhere_onnx_plugin_c_api.hsdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin.cppsdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin.hsdk/runanywhere-flutter/packages/runanywhere_onnx/windows/runanywhere_onnx_plugin_c_api.cpp
💤 Files with no reviewable changes (1)
- examples/flutter/RunAnywhereAI/.gitignore
| flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin()); | ||
| } catch (Exception e) { | ||
| Log.e(TAG, "Error registering plugin sqflite_android, com.tekartik.sqflite.SqflitePlugin", e); | ||
| Log.e(TAG, "Error registering plugin sqflite, com.tekartik.sqflite.SqflitePlugin", e); |
There was a problem hiding this comment.
Generated file — change will be overwritten.
GeneratedPluginRegistrant.java is regenerated by the Flutter tool on every flutter pub get/build based on the resolved plugin set. Manual edits (including this log identifier rename) are not preserved. If this file is intended to be checked in, ensure it stays in sync with the actual plugin versions; otherwise consider gitignoring it.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@examples/flutter/RunAnywhereAI/android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java`
at line 106, The change modifies a generated file
(GeneratedPluginRegistrant.java) — revert any manual edits (including the Log.e
line referencing sqflite) and do not commit changes to
GeneratedPluginRegistrant; instead keep plugin config in pubspec.yaml and let
the Flutter tool regenerate the file. If you need persistent custom behavior,
implement plugin registration or error handling in your app entrypoint (e.g.,
MainActivity or a custom registrant) rather than editing
GeneratedPluginRegistrant.java, and ensure GeneratedPluginRegistrant.java is
either kept in sync with pubspec-managed plugins or added to .gitignore if you
intentionally want it out of source control.
| extension ColorCompatibility on Color { | ||
| Color withValues({double? alpha}) { | ||
| if (alpha != null) { | ||
| return withOpacity(alpha.clamp(0.0, 1.0)); | ||
| } | ||
| return this; | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm the Flutter SDK constraint used by this example app.
fd -t f 'pubspec.yaml' examples/flutter/RunAnywhereAI -x cat {}
fd -t f 'pubspec.lock' examples/flutter/RunAnywhereAI -x grep -E '^(flutter|sdk):' {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 2261
🌐 Web query:
When was Color.withValues added to Flutter and when was ColorScheme.surfaceVariant deprecated?
💡 Result:
Color.withValues was added in Flutter 3.27.0. ColorScheme.surfaceVariant was deprecated after v3.18.0-0.1.pre, with the change landing in stable Flutter 3.22.0.
Citations:
- 1: https://docs.flutter.dev/release/breaking-changes/wide-gamut-framework
- 2: https://api.flutter.dev/flutter/material/ColorScheme/surfaceVariant.html
- 3: https://docs.flutter.dev/release/breaking-changes/new-color-scheme-roles
- 4: https://stackoverflow.com/questions/79481509/the-method-withvalues-isnt-defined-for-the-type-color
- 5: https://stackoverflow.com/questions/79481509/the-method-withvalues-isnt-defined-for-the-type-color/79481662
- 6: 3.27 Branch Info flutter/flutter#156508
- 7: https://blog.stackademic.com/flutter-3-22-update-breaking-changes-in-colorscheme-59ffb3131276
Confirm Flutter SDK support strategy — changes support older versions but incur deprecation on newer ones.
The project targets Flutter ≥3.10.0. Both changes are intentional backports:
Color.withValuesextension is necessary for Flutter 3.10–3.26 (the API didn't exist until 3.27.0), but becomes dead code (shadowed by the built-in instance method) on 3.27+.ColorScheme.surfaceVariantis not deprecated until Flutter 3.22.0; using it satisfies 3.10–3.21 but triggers deprecation warnings on 3.22+.
If the project must support Flutter 3.10.x, these changes are correct. If you're planning to upgrade the minimum to 3.27+ or 3.22+, consider using Color.withValues directly and ColorScheme.surfaceContainerHighest instead.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/flutter/RunAnywhereAI/lib/core/design_system/app_colors.dart` around
lines 3 - 10, Decide the supported minimum Flutter SDK and apply one of two
fixes: if you will keep minimum <3.27 (support 3.10–3.26) keep the backport
extension ColorCompatibility.withValues and usages of Color.withValues and keep
using ColorScheme.surfaceVariant but add clear comments and suppress deprecation
lints for future SDKs; if you raise the minimum to ≥3.27, remove the
ColorCompatibility extension and update all calls to Color.withValues to use the
built-in instance method, and if you raise the minimum to ≥3.22 replace uses of
ColorScheme.surfaceVariant with ColorScheme.surfaceContainerHighest (or the
recommended replacement) across the codebase. Ensure changes reference the
symbols ColorCompatibility.withValues, Color.withValues calls, and
ColorScheme.surfaceVariant so reviewers can find and verify the updates.
There was a problem hiding this comment.
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 (2)
sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp (1)
330-407:⚠️ Potential issue | 🟡 MinorAdd regression test for
NESTED_DIRECTORYwhen root contains visible files.The behavior change is intentional and documented (Whisper STT fix at lines 348-351), but the fallback path—returning root when visible files exist—is untested. The current test (
test_find_model_nested_directory) only exercises the happy path (single nested dir, no root files). Add a test case with a single nested directory alongside root-level files (e.g., README, LICENSE) to verify the fallback behavior works as designed.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp` around lines 330 - 407, Add a regression test that verifies the NESTED_DIRECTORY logic when the archive root contains visible files: create a temp directory with a single visible subdirectory plus at least one visible root file (e.g., README or LICENSE), call the function find_nested_directory (the behavior implemented in download_orchestrator.cpp) and assert it returns the original root path (not the single subdirectory); update or extend the existing test_find_model_nested_directory unit test to include this case so the fallback-to-root behavior is exercised and prevents regressions.sdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dart (1)
450-464:⚠️ Potential issue | 🟡 MinorPublish an SDK event when a download is cancelled.
The download is published as started at line 231 and failed in the catch block (line 456), but no corresponding event is published when cancelled at line 450. This leaves EventBus subscribers without a terminal event for cancellation, breaking the start-complete/start-failed pattern. The
SDKModelEventclass currently hasdownloadStarted,downloadCompleted,downloadFailed, anddownloadProgressmethods, but nodownloadCancelledvariant. AdddownloadCancelled()toSDKModelEventand publish it in theon _DownloadCancelledExceptionblock.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dart` around lines 450 - 464, Add a terminal cancellation event to keep EventBus subscribers consistent: extend SDKModelEvent with a new factory/method downloadCancelled({required String modelId}) and then publish it inside the on _DownloadCancelledException handler in download_service.dart (where ModelDownloadProgress.cancelled(modelId) is yielded). Specifically, update SDKModelEvent to include downloadCancelled and call EventBus.shared.publish(SDKModelEvent.downloadCancelled(modelId: modelId)) in the _DownloadCancelledException block alongside the existing _logger.info and ModelDownloadProgress.cancelled yield, ensuring subscribers receive a start-cancelled terminal event.
🧹 Nitpick comments (3)
sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp (1)
158-162: Tighten the auxiliary detection to a prefix check.A substring search will also match unrelated files that happen to contain
mmproj(e.g., a hypotheticalsomething-mmproj-removed.ggufor a model whose author embedded the token). Real llama.cpp projector artifacts ship with a strictmmprojfilename prefix (mmproj-…gguf,mmproj.gguf), so a prefix test is more precise and still covers the documented use case.♻️ Proposed refactor
static bool is_auxiliary_model_file(const std::string& filename) { std::string lower(filename); for (auto& c : lower) c = static_cast<char>(tolower(c)); - return lower.find("mmproj") != std::string::npos; + return lower.rfind("mmproj", 0) == 0; // basename starts with "mmproj" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp` around lines 158 - 162, The is_auxiliary_model_file function currently uses a substring search which can false-positive; change it to test only for a filename prefix "mmproj". Specifically, in is_auxiliary_model_file(const std::string& filename) convert the filename to lowercase as done now and replace the find(...) check with a prefix check (e.g., compare the first 6 characters or use rfind(..., 0) / compare(0,6,"mmproj") == 0) so it only returns true when the filename begins with "mmproj" (covering "mmproj", "mmproj.gguf", "mmproj-…gguf", etc.).examples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dart (1)
167-167: Hardcoded keychain prefix risks silent drift.
'com.runanywhere.RunAnywhereAI_'is duplicated from production code (likelyKeychainHelper). If that prefix changes, these tests continue to pass against an emptysecureStore(storage writes go to a different key namespace). Consider importing the actual prefix constant from the source so tests fail loudly on drift.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dart` at line 167, The test uses a hardcoded key prefix in the _prefixed helper which can drift from production; replace the hardcoded string with the authoritative prefix constant from the production Keychain helper (e.g., import and use KeychainHelper.keyPrefix or the actual constant name used in the source) so _prefixed(String key) returns '${KeychainHelper.keyPrefix}$key' (or equivalent) and the tests will fail if the production prefix changes.examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart (1)
19-19:decodeJson()cast is unsafe for non-object payloads.
jsonDecode(body) as Map<String, dynamic>will throw aTypeError(not a cleanFormatException) if the response body is a JSON array, primitive, or empty. Given this is the shared decode path for arbitrary endpoints (weather/geocoding per the summary), consider returningdynamicor guarding the cast and raising a typed error so callers can distinguish "non-JSON-object response" from network failures.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart` at line 19, The decodeJson() helper currently does an unsafe cast (jsonDecode(body) as Map<String, dynamic>) which will throw a TypeError for arrays/primitives/empty bodies; update decodeJson() to call jsonDecode(body) into a local var, check its runtime type, and if it's a Map<String, dynamic> return it, otherwise either return dynamic (change signature to dynamic) or throw a FormatException with a clear message like "expected JSON object but got <type>" so callers can distinguish malformed payloads from network errors; locate the decodeJson function in example_http_service.dart and implement the guard and appropriate return/exception behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart`:
- Around line 27-56: Both getJson and testProxy can hang because only
connectionTimeout is set; add per-request timeouts by applying timeout(...) to
the request.close() futures and to the body read
(response.transform(utf8.decoder).join()) in getJson, or alternatively set
client.idleTimeout on the HttpClient returned by createScopedHttpClient(scope,
uri) before making requests; catch and handle TimeoutException (and rethrow or
convert to a friendly error) so callers of getJson and testProxy receive a
deterministic failure instead of waiting indefinitely. Ensure you update both
getJson and testProxy call paths (referencing createScopedHttpClient,
request.close(), and response.transform(...).join()) to use the chosen timeout
approach and proper exception handling.
- Around line 74-94: The current code computes proxyDirective once using
targetUri.host and ignores the Uri passed into client.findProxy, so redirects to
different hosts (e.g., localhost) bypass _shouldUseProxy checks; change
client.findProxy to call _findProxyDirective(uri, uri.host) (or re-evaluate
_shouldUseProxy inside the closure) for each incoming Uri to determine the
directive per-request, while optionally keeping the initial pre-flight call to
_findProxyDirective(targetUri.host) if you want early validation; update
references to proxyDirective and ensure client.findProxy returns the per-request
result (falling back to 'DIRECT' when null).
- Around line 136-149: The current _proxyDirectiveForSettings returns a PROXY
directive for ProxyScheme.https which is incorrect because Dart's
HttpClient.findProxy cannot perform TLS to the proxy; update the implementation
so HTTPS is not treated as a plain PROXY: either remove ProxyScheme.https from
the set exposed by isSupportedInExampleApp (so the UI cannot select https), or
change _proxyDirectiveForSettings and related UI logic to avoid returning 'PROXY
...' for ProxyScheme.https and instead implement custom TLS-over-socket proxy
handling if you need true HTTPS-to-proxy support; locate and edit
_proxyDirectiveForSettings and the isSupportedInExampleApp logic around
ProxyScheme to apply the chosen fix.
In
`@examples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dart`:
- Around line 118-150: The save() implementation writes to SharedPreferences
first and then to KeychainHelper.saveString/delete, so if any keychain call
throws the prefs changes remain persisted while _current[scope] is not updated;
wrap the keychain operations (KeychainHelper.saveString/delete) in a try/catch
and either (a) on error revert the earlier prefs changes using the previous
values you read before writing (or remove the new keys) and return a non-valid
ProxySettingsValidationResult carrying the error, or (b) postpone updating
_current[scope] until after all keychain ops succeed and if a keychain call
fails catch it and return a non-valid ProxySettingsValidationResult without
mutating _current; ensure the code references save(),
KeychainHelper.saveString/delete, _current[scope], and
ProxySettingsValidationResult when making the fix.
In
`@examples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dart`:
- Around line 14-47: The tests leak state because ProxySettingsService.shared
caches ProxySettings returned by getCurrent; add a test-only reset to clear that
cache before each test. Implement a `@visibleForTesting` method like
ProxySettingsService.resetForTesting() (or expose a clearCache/clear() on the
singleton) and call ProxySettingsService.shared.resetForTesting() in setUp
(alongside secureStore.clear() and SharedPreferences.setMockInitialValues) so
each test starts with no cached ProxySettings.
In `@sdk/runanywhere-commons/scripts/build-windows.bat`:
- Around line 139-146: The Sherpa-ONNX DLL copy loop under the BUILD_ONNX check
silently succeeds when no DLLs are present; mirror the ONNX Runtime logic by
tracking whether any files were copied (e.g., introduce a flag like
SHERPA_ONNX_FOUND initialized to 0 and set to 1 when a copy succeeds in the for
loops that iterate over the sherpa-onnx DLL patterns), then after both loops
check the flag and if still 0 emit an error message and exit with non-zero
status (use the same style as the ONNX Runtime block), making sure to reference
the BUILD_ONNX conditional and the DIST_DIR copy target so the build fails early
when sherpa-onnx artifacts are missing.
- Line 4: The script sets BACKENDS=llamacpp by default causing Windows release
zips to omit ONNX artifacts; change the default BACKENDS value in
build-windows.bat from "llamacpp" to "all" (or ensure release.yml passes "all")
so rac_backend_onnx.dll, ONNX Runtime and Sherpa-ONNX DLLs are built and
packaged; additionally, add explicit existence/error checking around the
Sherpa-ONNX copy block by introducing and setting a flag (e.g.,
FOUND_SHERPA_ONNX) when expected Sherpa-ONNX files are located and copied, and
fail/exit with a clear error if the flag is not set (analogous to the ONNX
Runtime check) to avoid silently producing incomplete artifacts.
In `@sdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cpp`:
- Around line 252-256: The onnx_stt_can_handle implementation currently returns
TRUE for any existing directory; update it to verify the directory contains the
expected ONNX artifacts before claiming ownership (e.g., check for files like
"encoder.onnx", "decoder.onnx", and "tokens.txt" as onnx_backend.cpp scans).
Modify rac_backend_onnx_register::onnx_stt_can_handle (or the function named
onnx_stt_can_handle in the diff) to test for the presence/readability of those
specific files (using stat/access or directory enumeration) and only return
RAC_TRUE when they exist; otherwise return RAC_FALSE and adjust the
RAC_LOG_INFO/RAC_LOG_DEBUG messages to reflect whether required files were found
or missing. Ensure this validation prevents false positives that conflict with
other backends registering at the same priority.
In `@sdk/runanywhere-flutter/packages/runanywhere/test/platform_loader_test.dart`:
- Around line 5-17: The test fails on non-Windows CI because the code uses
File(resolvedExecutablePath).parent.path which is platform-dependent; update
PlatformLoader.windowsLibrarySearchPathsForTesting to compute the executable
directory using a Windows path context: replace
File(resolvedExecutablePath).parent.path with p.Context(style:
p.Style.windows).dirname(resolvedExecutablePath) (and add the necessary import
for package:path as p) so the Windows-style dirname is derived consistently on
all platforms.
---
Outside diff comments:
In
`@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp`:
- Around line 330-407: Add a regression test that verifies the NESTED_DIRECTORY
logic when the archive root contains visible files: create a temp directory with
a single visible subdirectory plus at least one visible root file (e.g., README
or LICENSE), call the function find_nested_directory (the behavior implemented
in download_orchestrator.cpp) and assert it returns the original root path (not
the single subdirectory); update or extend the existing
test_find_model_nested_directory unit test to include this case so the
fallback-to-root behavior is exercised and prevents regressions.
In
`@sdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dart`:
- Around line 450-464: Add a terminal cancellation event to keep EventBus
subscribers consistent: extend SDKModelEvent with a new factory/method
downloadCancelled({required String modelId}) and then publish it inside the on
_DownloadCancelledException handler in download_service.dart (where
ModelDownloadProgress.cancelled(modelId) is yielded). Specifically, update
SDKModelEvent to include downloadCancelled and call
EventBus.shared.publish(SDKModelEvent.downloadCancelled(modelId: modelId)) in
the _DownloadCancelledException block alongside the existing _logger.info and
ModelDownloadProgress.cancelled yield, ensuring subscribers receive a
start-cancelled terminal event.
---
Nitpick comments:
In `@examples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dart`:
- Line 19: The decodeJson() helper currently does an unsafe cast
(jsonDecode(body) as Map<String, dynamic>) which will throw a TypeError for
arrays/primitives/empty bodies; update decodeJson() to call jsonDecode(body)
into a local var, check its runtime type, and if it's a Map<String, dynamic>
return it, otherwise either return dynamic (change signature to dynamic) or
throw a FormatException with a clear message like "expected JSON object but got
<type>" so callers can distinguish malformed payloads from network errors;
locate the decodeJson function in example_http_service.dart and implement the
guard and appropriate return/exception behavior.
In
`@examples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dart`:
- Line 167: The test uses a hardcoded key prefix in the _prefixed helper which
can drift from production; replace the hardcoded string with the authoritative
prefix constant from the production Keychain helper (e.g., import and use
KeychainHelper.keyPrefix or the actual constant name used in the source) so
_prefixed(String key) returns '${KeychainHelper.keyPrefix}$key' (or equivalent)
and the tests will fail if the production prefix changes.
In
`@sdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cpp`:
- Around line 158-162: The is_auxiliary_model_file function currently uses a
substring search which can false-positive; change it to test only for a filename
prefix "mmproj". Specifically, in is_auxiliary_model_file(const std::string&
filename) convert the filename to lowercase as done now and replace the
find(...) check with a prefix check (e.g., compare the first 6 characters or use
rfind(..., 0) / compare(0,6,"mmproj") == 0) so it only returns true when the
filename begins with "mmproj" (covering "mmproj", "mmproj.gguf", "mmproj-…gguf",
etc.).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: eaf7e827-3e5b-461e-97be-bf17a4ee60fd
📒 Files selected for processing (22)
examples/flutter/RunAnywhereAI/lib/app/runanywhere_ai_app.dartexamples/flutter/RunAnywhereAI/lib/core/services/example_http_service.dartexamples/flutter/RunAnywhereAI/lib/core/services/proxy_settings_service.dartexamples/flutter/RunAnywhereAI/lib/features/chat/chat_interface_view.dartexamples/flutter/RunAnywhereAI/lib/features/rag/rag_demo_view.dartexamples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dartexamples/flutter/RunAnywhereAI/lib/features/settings/tool_settings_view_model.dartexamples/flutter/RunAnywhereAI/lib/features/voice/speech_to_text_view.dartexamples/flutter/RunAnywhereAI/lib/features/voice/text_to_speech_view.dartexamples/flutter/RunAnywhereAI/lib/features/voice/voice_assistant_view.dartexamples/flutter/RunAnywhereAI/test/core/models/proxy_settings_test.dartexamples/flutter/RunAnywhereAI/test/core/services/example_http_service_test.dartexamples/flutter/RunAnywhereAI/test/core/services/proxy_settings_service_test.dartexamples/flutter/RunAnywhereAI/test/widget_test.dartsdk/runanywhere-commons/scripts/build-windows.batsdk/runanywhere-commons/src/backends/onnx/rac_backend_onnx_register.cppsdk/runanywhere-commons/src/infrastructure/download/download_orchestrator.cppsdk/runanywhere-commons/tests/test_download_orchestrator.cppsdk/runanywhere-flutter/packages/runanywhere/lib/infrastructure/download/download_service.dartsdk/runanywhere-flutter/packages/runanywhere/lib/native/platform_loader.dartsdk/runanywhere-flutter/packages/runanywhere/test/download_service_test.dartsdk/runanywhere-flutter/packages/runanywhere/test/platform_loader_test.dart
✅ Files skipped from review due to trivial changes (2)
- examples/flutter/RunAnywhereAI/test/core/models/proxy_settings_test.dart
- sdk/runanywhere-flutter/packages/runanywhere/test/download_service_test.dart
🚧 Files skipped from review as they are similar to previous changes (6)
- sdk/runanywhere-flutter/packages/runanywhere/lib/native/platform_loader.dart
- examples/flutter/RunAnywhereAI/test/core/services/example_http_service_test.dart
- examples/flutter/RunAnywhereAI/test/widget_test.dart
- examples/flutter/RunAnywhereAI/lib/features/settings/tool_settings_view_model.dart
- examples/flutter/RunAnywhereAI/lib/features/chat/chat_interface_view.dart
- examples/flutter/RunAnywhereAI/lib/features/settings/combined_settings_view.dart

Description
Brief description of the changes made.
Type of Change
Testing
Platform-Specific Testing (check all that apply)
Swift SDK / iOS Sample:
Kotlin SDK / Android Sample:
Flutter SDK / Flutter Sample:
React Native SDK / React Native Sample:
Playground:
Web SDK / Web Sample:
Labels
Please add the appropriate label(s):
SDKs:
Swift SDK- Changes to Swift SDK (sdk/runanywhere-swift)Kotlin SDK- Changes to Kotlin SDK (sdk/runanywhere-kotlin)Flutter SDK- Changes to Flutter SDK (sdk/runanywhere-flutter)React Native SDK- Changes to React Native SDK (sdk/runanywhere-react-native)Web SDK- Changes to Web SDK (sdk/runanywhere-web)Commons- Changes to shared native code (sdk/runanywhere-commons)Sample Apps:
iOS Sample- Changes to iOS example app (examples/ios)Android Sample- Changes to Android example app (examples/android)Flutter Sample- Changes to Flutter example app (examples/flutter)React Native Sample- Changes to React Native example app (examples/react-native)Web Sample- Changes to Web example app (examples/web)Checklist
Screenshots
Attach relevant UI screenshots for changes (if applicable):
Note
Medium Risk
Adds a new Windows desktop build target (CMake runner + camera plugin) and threads new proxy configuration into HTTP/download flows, touching networking and platform-specific initialization paths. Risk is moderate due to new persistence/credential handling and Windows-only feature gating that could cause regressions on edge platforms/builds.
Overview
Adds Windows desktop support for the Flutter example app by introducing a full
windows/runner + plugin registration, pinningcamera_windows, and documenting Windows build/validation steps for ONNX voice and Vision.Introduces scoped proxy settings (
generalvsdownload) persisted viaSharedPreferences+ Keychain/secure storage, a newExampleHttpServicethat applies proxy directives/credentials, and hooks download traffic into the SDK viaRunAnywhere.configureDownloadHttpClientFactory.Updates the Flutter app to better handle Windows limitations: gates RAG (and some model-selection options) behind a
PlatformCapabilityServicewith consistentUnsupportedFeatureViewUX, refactors Vision camera handling behind injectable backend/session interfaces, and includes small compatibility/test fixes (dropdownvalueusage, plugin registrant tweaks, rethrow on model load failure).Reviewed by Cursor Bugbot for commit c3b45a9. Configure here.
Summary by CodeRabbit
New Features
Improvements
Tests & Docs