feat: add iOS TTS support using ONNX Runtime - #378
AnthonyRonning wants to merge 22 commits into
Conversation
📝 WalkthroughWalkthroughAdds iOS on-device TTS support via ONNX Runtime: CI caches or builds an xcframework, verifies artifacts, generates an absolute Cargo config, exposes ORT_LIB_LOCATION to the Tauri iOS build, adds scripts to download/build XCFrameworks, and wires iOS TTS runtime and UI error reporting in frontend code. Changes
Sequence Diagram(s)sequenceDiagram
participant CI as GitHub Actions
participant Cache as Actions Cache
participant HF as HuggingFace
participant Script as setup/build script
participant FS as Runner FS
participant CargoCfg as .cargo/config.toml
participant Tauri as Tauri iOS Build
participant App as iOS App Runtime
CI->>Cache: check for ONNX xcframework cache
alt cache hit
Cache-->>CI: restore xcframework into FS
else cache miss
CI->>Script: run setup-ios-onnxruntime.sh or build-ios-onnxruntime.sh
Script->>HF: download assets or clone & build source
Script-->>FS: produce xcframework at path
CI->>Cache: save xcframework to cache
end
CI->>CargoCfg: write absolute linker paths (ORT_LIB_LOCATION)
CI->>Tauri: run iOS build with ORT_LIB_LOCATION env
Tauri->>CargoCfg: compile and link static onnxruntime
Tauri-->>App: produce iOS artifact with linked ONNX Runtime
App->>App: runtime TTS handlers call into ONNX Runtime
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
Deploying maple with
|
| Latest commit: |
d146705
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://478d8a0b.maple-ca8.pages.dev |
| Branch Preview URL: | https://ios-tts-working-ci.maple-ca8.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @frontend/src-tauri/scripts/setup-ios-onnxruntime.sh:
- Around line 51-53: The curl invocation that downloads Info.plist (the line
starting with curl -L -o "$XCFRAMEWORK_DIR/Info.plist"
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist") should include
the --fail flag so HTTP errors cause curl to exit non‑zero; update this curl
command and all other curl invocations in the script (the other download lines)
to use --fail (e.g., curl --fail -L -o ...) so the script’s set -e error
handling catches HTTP failures.
🧹 Nitpick comments (3)
frontend/src-tauri/src/lib.rs (1)
269-317: Consider consolidating duplicated setup logic.The Android (lines 275-288) and iOS (lines 303-316) setup blocks have identical deep link handler code. While functional, this duplication could be reduced.
♻️ Optional: Extract shared mobile setup into a helper
You could extract the common deep link setup into a helper function to reduce duplication:
#[cfg(not(desktop))] fn setup_mobile_deep_links(app: &tauri::App) -> Result<(), Box<dyn std::error::Error>> { let app_handle = app.handle().clone(); app.deep_link().on_open_url(move |event| { if let Some(url) = event.urls().first() { handle_deep_link_event(url.as_ref(), &app_handle); } }); Ok(()) }Then call it from both Android and iOS setup blocks.
.github/workflows/mobile-build.yml (1)
56-64: Consider removing the restore-keys to prevent incompatible version restoration.The
restore-keyspattern could restore a cached older version of ONNX Runtime when the version changes from 1.20.1 to 1.20.2+. This could lead to build failures or runtime issues if the API or binary format is incompatible.Since the setup script is idempotent and relatively fast (~100-200MB download), it's safer to only use an exact version match.
♻️ Proposed fix to remove restore-keys
- name: Cache ONNX Runtime iOS xcframework uses: actions/cache@v4 id: cache-onnxruntime with: path: frontend/src-tauri/onnxruntime-ios key: onnxruntime-ios-1.20.1 - restore-keys: | - onnxruntime-ios-frontend/src-tauri/scripts/setup-ios-onnxruntime.sh (1)
1-16: Consider adding stricter error handling flags.The script uses
set -ewhich is good, but adding-u(exit on undefined variables) and-o pipefail(exit on pipe failures) would make the script more robust. This is especially important for build scripts that download external dependencies.♻️ Proposed enhancement for error handling
-set -e +set -euo pipefailThis ensures:
-e: Exit on any command failure-u: Exit on undefined variable usage-o pipefail: Exit if any command in a pipe fails (not just the last one)
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.ymlfrontend/src-tauri/.gitignorefrontend/src-tauri/Cargo.tomlfrontend/src-tauri/build.rsfrontend/src-tauri/scripts/setup-ios-onnxruntime.shfrontend/src-tauri/src/lib.rsfrontend/src-tauri/src/tts.rsfrontend/src/services/tts/TTSContext.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use path aliases (@/*maps to./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid usinganytype
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Runjust format,just lint, andjust buildafter making TypeScript/React changes to ensure code quality and compilation
Files:
frontend/src/services/tts/TTSContext.tsx
🧠 Learnings (3)
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/testflight-on-comment.yml
📚 Learning: 2025-03-25T19:50:07.925Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 23
File: frontend/src-tauri/src/lib.rs:14-16
Timestamp: 2025-03-25T19:50:07.925Z
Learning: In Tauri applications, updater security configurations (including endpoints, public key for verification, and dialog settings) should be defined in the tauri.conf.json file rather than duplicated in the code. When initialized with tauri_plugin_updater::Builder::new().build(), the plugin automatically reads and uses these settings from the configuration file.
Applied to files:
frontend/src-tauri/src/lib.rs
📚 Learning: 2025-03-25T19:50:07.925Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 23
File: frontend/src-tauri/src/lib.rs:14-16
Timestamp: 2025-03-25T19:50:07.925Z
Learning: In Tauri applications, the updater configuration (including security settings like server URL and public key) should be defined in tauri.conf.json rather than hardcoded in the application code. The code only needs to initialize the updater plugin with tauri_plugin_updater::Builder::new().build(), which will automatically use the settings from the configuration file.
Applied to files:
frontend/src-tauri/src/lib.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-android
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (13)
frontend/src-tauri/.gitignore (1)
5-7: LGTM!Correctly ignores the downloaded ONNX Runtime iOS xcframework directory, which aligns with the setup script and CI caching strategy.
frontend/src/services/tts/TTSContext.tsx (2)
10-10: LGTM!Import correctly uses the
@/*path alias as per coding guidelines.
63-64: LGTM!The environment detection logic correctly extends TTS availability to iOS while excluding Android. Both
isIOSandisTaurifunctions are properly exported fromfrontend/src/utils/platform.tsand correctly imported using the path alias in TTSContext.tsx. The comment clearly documents the intent.frontend/src-tauri/build.rs (2)
2-30: LGTM!The iOS build configuration correctly sets up static linking for ONNX Runtime, links required iOS frameworks (Foundation, Accelerate), and sets the
ORT_LIB_LOCATIONenvironment variable for theortcrate.
10-15: Directory structure and target detection are correct.The xcframework directory names in build.rs (
ios-arm64_x86_64-simulatorandios-arm64) match the structure created by the setup script. The target detection logic correctly routes simulator targets (containing "sim" or "x86_64") to the simulator xcframework and device targets to the device variant.frontend/src-tauri/src/lib.rs (2)
6-8: LGTM!The conditional compilation correctly enables the TTS module for both desktop and iOS platforms.
263-267: LGTM!TTS state management is correctly added for iOS, mirroring the desktop configuration.
frontend/src-tauri/src/tts.rs (1)
614-633: LGTM!The iOS-specific path handling correctly uses the app's Documents directory, which is appropriate for user-downloadable content that should persist across app updates. The
HOMEenvironment variable approach is standard for iOS apps. The early return for iOS ensures thedirscrate is never called on that platform, so including it in iOS dependencies poses no issues..github/workflows/testflight-on-comment.yml (1)
114-128: LGTM!The ONNX Runtime caching configuration is well-structured:
- Version-specific cache key (1.20.1) matches the script default, enabling proper cache invalidation on updates
- Conditional download avoids redundant work on cache hits
- Script at
frontend/src-tauri/scripts/setup-ios-onnxruntime.shexists and is properly structured- Cache path and working directory are correctly aligned with the setup script expectations
frontend/src-tauri/Cargo.toml (1)
56-69: LGTM!The iOS dependency configuration appropriately differs from desktop:
ortwithdefault-features = falsefor static linking compatibility with the pre-built xcframeworkndarraywithout therayonfeature, which is sensible for iOSThe
dirscrate is included in the iOS dependencies but won't be used sinceget_tts_models_dir()returns early with the HOME-based path on iOS..github/workflows/mobile-build.yml (1)
65-71: LGTM!The conditional download step is well-implemented:
- Only runs on cache miss to avoid redundant downloads
- Sets executable permissions before running the script
- Working directory aligns with the script's expectations
frontend/src-tauri/scripts/setup-ios-onnxruntime.sh (2)
17-22: LGTM!The idempotency check is well-implemented:
- Prevents redundant downloads when the xcframework already exists
- Exits successfully (status 0) to allow the workflow to continue
- Provides clear guidance for manual re-download if needed
61-78: Good user feedback and verification output.The script provides:
- Clear progress messages with time expectations for large downloads
- Verification output showing downloaded contents and file sizes
- Helpful debugging information with
lscommandsThis makes troubleshooting download issues much easier.
| # Create directory | ||
| mkdir -p "$ORT_DIR" | ||
|
|
||
| # Download pre-built xcframework from HuggingFace | ||
| # Repository: https://huggingface.co/csukuangfj/ios-onnxruntime | ||
| HF_BASE_URL="https://huggingface.co/csukuangfj/ios-onnxruntime/resolve/main" | ||
|
|
||
| echo "Downloading ONNX Runtime $ORT_VERSION xcframework from HuggingFace..." | ||
|
|
||
| # Download the xcframework directory structure | ||
| # The structure is: | ||
| # onnxruntime.xcframework/ | ||
| # Info.plist | ||
| # Headers/ | ||
| # cpu_provider_factory.h | ||
| # onnxruntime_c_api.h | ||
| # onnxruntime_cxx_api.h | ||
| # onnxruntime_cxx_inline.h | ||
| # ios-arm64/ | ||
| # onnxruntime.a | ||
| # ios-arm64_x86_64-simulator/ | ||
| # onnxruntime.a | ||
|
|
||
| mkdir -p "$XCFRAMEWORK_DIR/Headers" | ||
| mkdir -p "$XCFRAMEWORK_DIR/ios-arm64" | ||
| mkdir -p "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator" | ||
|
|
There was a problem hiding this comment.
Document the third-party dependency and consider verification steps.
The script downloads pre-built binaries from a third-party HuggingFace repository (csukuangfj/ios-onnxruntime). While convenient, this introduces supply chain security considerations:
- No checksum or signature verification of downloaded files
- Dependency on a third-party maintainer's infrastructure
- Potential for compromise or unavailability
Consider adding:
- SHA256 checksum verification for downloaded files
- Documentation about the trust model and why this source is acceptable
- A fallback mechanism or alternative source
Example checksum verification approach:
# After downloading, verify checksums
EXPECTED_ARM64_SHA256="<hash_here>"
ACTUAL_SHA256=$(shasum -a 256 "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" | cut -d' ' -f1)
if [ "$ACTUAL_SHA256" != "$EXPECTED_ARM64_SHA256" ]; then
echo "ERROR: Checksum verification failed for ios-arm64 library"
exit 1
fi| echo "Downloading Info.plist..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add --fail flag to curl commands to catch HTTP errors.
Without --fail, curl will silently write error HTML pages (like 404 responses) to the output files, which could lead to cryptic build failures later. The --fail flag ensures curl exits with a non-zero status on HTTP errors, leveraging the set -e error handling.
♻️ Proposed fix to add --fail to all curl commands
This issue applies to all curl commands in the script (lines 52, 57-58, 62-63, 66-67). Here's the fix for this specific download:
echo "Downloading Info.plist..."
-curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \
+curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist"Apply the same change to all other curl commands in the script.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| echo "Downloading Info.plist..." | |
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading Info.plist..." | |
| curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" |
🤖 Prompt for AI Agents
In @frontend/src-tauri/scripts/setup-ios-onnxruntime.sh around lines 51 - 53,
The curl invocation that downloads Info.plist (the line starting with curl -L -o
"$XCFRAMEWORK_DIR/Info.plist"
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist") should include
the --fail flag so HTTP errors cause curl to exit non‑zero; update this curl
command and all other curl invocations in the script (the other download lines)
to use --fail (e.g., curl --fail -L -o ...) so the script’s set -e error
handling catches HTTP failures.
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR extends Text-to-Speech (TTS) functionality from desktop-only to include iOS support using ONNX Runtime. The implementation follows the existing desktop architecture, downloading TTS models (~264MB) on-demand and storing them in the iOS Documents directory.
Key Changes
Build System: New setup-ios-onnxruntime.sh script downloads pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace. The build configuration (build.rs) adds iOS-specific linker flags for the static ONNX Runtime library and required iOS frameworks (Foundation, Accelerate).
Dependencies: iOS-specific dependencies mirror desktop TTS dependencies with one key difference—ndarray omits the rayon feature on iOS (appropriate since rayon's threading may not work reliably on mobile).
Platform Detection: The frontend correctly updates TTS availability from desktop-only to include iOS using the existing platform detection utilities (isTauriDesktop() || (isTauri() && isIOS())).
Configuration Split: The lib.rs mobile configuration has been properly split into separate iOS and Android blocks. iOS gets TTS state management and TTS-specific commands, while Android continues with the minimal configuration (PDF extraction only).
Architecture Integration
The iOS implementation reuses the entire desktop TTS codebase without modification, except for the model storage path. On iOS, models are stored at ~/Documents/tts_models instead of using the system's data directory. The ONNX inference pipeline, text preprocessing, and audio generation remain identical across platforms.
Issues Found
-
Path Handling Risk: The iOS path resolution uses
std::env::var("HOME")which may be unreliable in sandboxed iOS apps. This could cause TTS initialization to fail even when the Documents directory is accessible. -
Download Security: The xcframework download script lacks checksum validation and proper HTTP error handling (no
--failflag on curl). This creates supply chain security risks—corrupted or tampered downloads could cause cryptic build failures or compromise the build. -
Minor Code Quality: Build script uses
.unwrap()which provides poor error messages on failure.
Testing Gaps
The PR description shows the testing checklist is incomplete—no tests have been run yet on simulator or physical devices, and model download/playback verification is pending.
Confidence Score: 3/5
- This PR has solid architectural decisions but contains reliability and security issues that should be addressed before merging
- The score reflects well-structured platform-specific configuration and correct dependency management, but is lowered due to: (1) unreliable iOS path resolution that could cause runtime failures, (2) supply chain security concerns from unvalidated xcframework downloads, and (3) lack of testing verification. The core TTS logic is proven from desktop, but the iOS-specific integration points need hardening.
- Pay special attention to frontend/src-tauri/src/tts.rs (iOS path handling) and frontend/src-tauri/scripts/setup-ios-onnxruntime.sh (download validation)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 3/5 | Downloads ONNX Runtime xcframework from HuggingFace without checksum validation or proper error handling, creating potential supply chain security risks |
| frontend/src-tauri/src/tts.rs | 3/5 | Adds iOS path handling using unreliable HOME environment variable instead of proper iOS APIs, may fail in sandboxed environments |
| frontend/src-tauri/build.rs | 4/5 | Adds iOS-specific ONNX Runtime linker configuration, uses unwrap() which could provide better error messages |
| frontend/src-tauri/src/lib.rs | 4/5 | Properly splits mobile configuration into separate iOS and Android blocks, adds TTS commands for iOS |
Sequence Diagram
sequenceDiagram
participant User
participant TTSContext as TTSContext.tsx
participant Tauri as Tauri Bridge
participant TTS as tts.rs
participant ONNX as ONNX Runtime
participant HF as HuggingFace
Note over User,HF: TTS Initialization Flow (iOS)
User->>TTSContext: App loads on iOS
TTSContext->>Tauri: invoke("tts_get_status")
Tauri->>TTS: tts_get_status()
TTS->>TTS: Check ~/Documents/tts_models
TTS-->>Tauri: {models_downloaded: false, models_loaded: false}
Tauri-->>TTSContext: Status response
TTSContext->>TTSContext: Set status: "not_downloaded"
Note over User,HF: Model Download Flow
User->>TTSContext: Click download models
TTSContext->>Tauri: invoke("tts_download_models")
Tauri->>TTS: tts_download_models()
loop For each model file
TTS->>HF: Download model file (~264MB total)
HF-->>TTS: Model file chunks
TTS->>TTS: Verify SHA256 checksum
TTS->>Tauri: Emit download progress
Tauri-->>TTSContext: "tts-download-progress" event
TTSContext->>TTSContext: Update progress UI
end
TTS-->>Tauri: Download complete
Tauri-->>TTSContext: Success
TTSContext->>Tauri: invoke("tts_load_models")
Tauri->>TTS: tts_load_models()
TTS->>ONNX: Load ONNX sessions
ONNX-->>TTS: Sessions loaded (~500MB RAM)
TTS-->>Tauri: Success
Tauri-->>TTSContext: Models loaded
TTSContext->>TTSContext: Set status: "ready"
Note over User,HF: Speech Synthesis Flow
User->>TTSContext: Request TTS for message
TTSContext->>TTSContext: Preprocess text (remove code/thinking)
TTSContext->>Tauri: invoke("tts_synthesize", {text})
Tauri->>TTS: tts_synthesize(text)
TTS->>TTS: Chunk text (~300 chars)
TTS->>TTS: Preprocess chunks
loop For each chunk
TTS->>ONNX: Predict duration
TTS->>ONNX: Encode text
TTS->>ONNX: Denoise latent (10 steps)
TTS->>ONNX: Generate waveform
end
TTS->>TTS: Concatenate audio chunks
TTS->>TTS: Encode to WAV base64
TTS-->>Tauri: {audio_base64, sample_rate, duration}
Tauri-->>TTSContext: Synthesis result
TTSContext->>TTSContext: Decode base64 to audio
TTSContext->>TTSContext: Play via Web Audio API
TTSContext->>User: Audio playback
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
The curl commands download large binary files without any validation or error handling. Several issues:
- Missing
--failflag: If the HuggingFace URL returns a 404 or other HTTP error, curl will save the error page as a valid file, causing cryptic build failures later - No checksum validation: Unlike the TTS model downloads in
tts.rswhich verify SHA256 checksums, these xcframework files are not validated - No retry logic: Network failures will cause the entire download to fail without retry
This could lead to corrupted builds or supply chain security issues if the downloaded files are tampered with.
Recommendation: Add --fail flag to all curl commands and consider adding checksum validation similar to the TTS model downloads.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 62:67
Comment:
The curl commands download large binary files without any validation or error handling. Several issues:
1. **Missing `--fail` flag**: If the HuggingFace URL returns a 404 or other HTTP error, curl will save the error page as a valid file, causing cryptic build failures later
2. **No checksum validation**: Unlike the TTS model downloads in `tts.rs` which verify SHA256 checksums, these xcframework files are not validated
3. **No retry logic**: Network failures will cause the entire download to fail without retry
This could lead to corrupted builds or supply chain security issues if the downloaded files are tampered with.
**Recommendation**: Add `--fail` flag to all curl commands and consider adding checksum validation similar to the TTS model downloads.
How can I resolve this? If you propose a fix, please make it concise.| { | ||
| // On iOS, use the app's Documents directory which is accessible and persists | ||
| // NSHomeDirectory() + /Documents/tts_models | ||
| let home = std::env::var("HOME").context("Failed to get HOME directory on iOS")?; |
There was a problem hiding this comment.
Using std::env::var("HOME") is unreliable on iOS. The HOME environment variable may not be set or may not point to the expected location in sandboxed iOS apps.
Issue: If HOME is not set, this will return an error and TTS will fail to initialize, even though the app directory is accessible through proper iOS APIs.
Recommendation: Consider using Tauri's path resolution APIs (e.g., app_handle.path().app_data_dir() or similar) instead of relying on environment variables. This would be more robust and consistent with how Tauri handles paths across platforms.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/tts.rs
Line: 620:620
Comment:
Using `std::env::var("HOME")` is unreliable on iOS. The HOME environment variable may not be set or may not point to the expected location in sandboxed iOS apps.
**Issue**: If HOME is not set, this will return an error and TTS will fail to initialize, even though the app directory is accessible through proper iOS APIs.
**Recommendation**: Consider using Tauri's path resolution APIs (e.g., `app_handle.path().app_data_dir()` or similar) instead of relying on environment variables. This would be more robust and consistent with how Tauri handles paths across platforms.
How can I resolve this? If you propose a fix, please make it concise.| #[cfg(target_os = "ios")] | ||
| { | ||
| // Get the path to the ONNX Runtime xcframework | ||
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); |
There was a problem hiding this comment.
Using .unwrap() in build scripts provides poor error messages when failures occur. While CARGO_MANIFEST_DIR should always be set during builds, if it's not set for any reason, the build will panic with an unhelpful error message.
Recommendation: Use .expect("CARGO_MANIFEST_DIR not set") to provide a more descriptive error message, or use .context() from anyhow if error handling is needed.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 6:6
Comment:
Using `.unwrap()` in build scripts provides poor error messages when failures occur. While `CARGO_MANIFEST_DIR` should always be set during builds, if it's not set for any reason, the build will panic with an unhelpful error message.
**Recommendation**: Use `.expect("CARGO_MANIFEST_DIR not set")` to provide a more descriptive error message, or use `.context()` from anyhow if error handling is needed.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech (TTS) support for iOS using ONNX Runtime, enabling the Supertonic TTS model to run on-device on iPhones and iPads. The implementation mirrors the existing desktop TTS functionality and makes the following key changes:
Core Changes:
- iOS Build Configuration: Downloads pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace during CI/CD builds, with caching to optimize build times
- Linker Setup: Configures iOS-specific static library linking in
build.rs, detecting simulator vs device targets and linking appropriate ONNX Runtime binaries along with Foundation and Accelerate frameworks - Module Enablement: Extends TTS module compilation from desktop-only to include iOS via
#[cfg(any(desktop, target_os = "ios"))] - iOS-Specific Storage: Uses
~/Documents/tts_modelsfor iOS model storage (vs platform-specific data directories on desktop) sincedirs::data_local_dir()may not work reliably on iOS - Frontend Detection: Updates
TTSContext.tsxto recognize iOS as a TTS-capable platform alongside desktop - Split Mobile Configuration: Separates Android and iOS invoke handlers in
lib.rsto add TTS commands only to iOS
Architecture:
The implementation uses pre-built static ONNX Runtime libraries (avoiding runtime binary downloads) and follows iOS sandboxing requirements. Models (~264MB) are downloaded on-demand at runtime and stored in the app's Documents directory. The TTS pipeline runs entirely on-device using iOS's Accelerate framework for neural network acceleration.
Integration Quality:
The changes are well-structured and maintain clean separation between platforms. The iOS implementation reuses the existing desktop TTS codebase with minimal platform-specific modifications (primarily path handling). GitHub Actions workflows properly cache the ONNX Runtime xcframework to avoid repeated downloads.
Confidence Score: 5/5
- This PR is safe to merge. The implementation is well-structured, platform-specific changes are properly isolated with cfg attributes, and the code follows established patterns from the desktop TTS implementation.
- All changes are isolated to iOS-specific code paths with proper conditional compilation. The build configuration correctly handles simulator and device targets. The iOS-specific storage path using ~/Documents is appropriate for the iOS sandbox. The GitHub Actions workflows properly cache dependencies. No breaking changes to existing desktop or Android functionality.
- No files require special attention. All implementations are correct and follow iOS development best practices.
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 5/5 | Adds ONNX Runtime xcframework download and caching before iOS build. Implementation is correct with proper cache keys. |
| .github/workflows/testflight-on-comment.yml | 5/5 | Adds identical ONNX Runtime setup as mobile-build.yml. Correctly placed before Xcode setup. |
| frontend/src-tauri/.gitignore | 5/5 | Adds /onnxruntime-ios/ to gitignore. Correctly excludes build-time downloaded dependencies. |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies with disabled default features for ort. Correctly mirrors desktop dependencies except for ndarray features. |
| frontend/src-tauri/build.rs | 5/5 | Adds iOS linker configuration for ONNX Runtime xcframework. Correctly detects simulator vs device targets and links appropriate static libraries. |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 5/5 | New script to download ONNX Runtime 1.20.1 xcframework from HuggingFace. Downloads Info.plist, headers, and static libraries for both device and simulator. |
| frontend/src-tauri/src/lib.rs | 5/5 | Enables TTS module for iOS and adds TTS commands to iOS invoke handler. Splits mobile configuration into separate Android and iOS blocks with appropriate handlers. |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling using ~/Documents/tts_models for model storage. Correctly uses HOME env var fallback for iOS. |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Updates isTauriEnv check to enable TTS on iOS alongside desktop. Correctly excludes Android. |
| frontend/bun.lock | 5/5 | Lockfile changes. No issues detected. |
Sequence Diagram
sequenceDiagram
participant User as User
participant UI as Frontend (TTSContext.tsx)
participant Tauri as Tauri IPC Bridge
participant Rust as Rust Backend (tts.rs)
participant ORT as ONNX Runtime
participant FS as File System
Note over User,FS: App Initialization (iOS)
UI->>UI: Check platform: isTauri() && isIOS()
UI->>Tauri: invoke("tts_get_status")
Tauri->>Rust: tts_get_status()
Rust->>FS: Check ~/Documents/tts_models/
FS-->>Rust: Directory status
Rust-->>Tauri: {models_downloaded, models_loaded, total_size_mb}
Tauri-->>UI: Status response
alt Models not downloaded
UI->>UI: Set status "not_downloaded"
User->>UI: Click download button
UI->>Tauri: invoke("tts_download_models")
Tauri->>Rust: tts_download_models()
loop For each model file
Rust->>Rust: Download from HuggingFace
Rust->>Tauri: emit("tts-download-progress")
Tauri->>UI: Progress event
UI->>UI: Update progress bar
end
Rust->>FS: Save models to ~/Documents/tts_models/
Rust-->>Tauri: Download complete
UI->>Tauri: invoke("tts_load_models")
end
Note over User,FS: Model Loading
Tauri->>Rust: tts_load_models()
Rust->>FS: Read model files from ~/Documents/tts_models/
FS-->>Rust: Model data
Rust->>ORT: Create ONNX sessions
ORT->>ORT: Load to iOS Accelerate framework
ORT-->>Rust: Sessions ready
Rust-->>Tauri: Models loaded
Tauri-->>UI: Success
UI->>UI: Set status "ready"
Note over User,FS: Text-to-Speech Synthesis
User->>UI: Click speak button
UI->>UI: Preprocess text (remove code blocks)
UI->>Tauri: invoke("tts_synthesize", {text})
Tauri->>Rust: tts_synthesize(text)
Rust->>Rust: Text preprocessing & normalization
Rust->>ORT: Run text_encoder session
ORT-->>Rust: Text embeddings
Rust->>ORT: Run duration_predictor session
ORT-->>Rust: Duration values
Rust->>ORT: Run vector_estimator session
ORT-->>Rust: Latent vectors
Rust->>ORT: Run vocoder session
ORT-->>Rust: WAV audio data
Rust->>Rust: Encode to base64
Rust-->>Tauri: {audio_base64, sample_rate, duration_seconds}
Tauri-->>UI: Audio response
UI->>UI: Decode base64 to Blob
UI->>UI: Create AudioContext
UI->>UI: Play audio via Web Audio API
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR successfully enables on-device Text-to-Speech for iOS using ONNX Runtime and the Supertonic model. The implementation mirrors the existing desktop TTS functionality with iOS-specific adaptations for static library linking and storage paths.
Major Changes:
- Downloads pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace during CI builds
- Configures iOS linker to use static ONNX Runtime libraries for simulator and device targets
- Stores TTS models in
~/Documents/tts_modelson iOS (sandboxed app directory) - Updates frontend platform detection to enable TTS on iOS (but not Android)
- Adds caching to CI workflows to speed up builds
Issues Found:
- Security concern: Download script lacks checksum verification (unlike the Rust download code which validates SHA256)
- CI reliability: No validation of cached xcframework files - broken cache could cause build failures
- Build validation:
build.rsdoesn't verify xcframework exists before setting linker flags, leading to cryptic errors if download fails
The implementation is architecturally sound with proper conditional compilation, correct platform detection, and appropriate error handling in the Rust code. The main concerns are around the CI/build pipeline's robustness and the security of the binary download process.
Confidence Score: 3/5
- Safe to merge with moderate risk - the runtime code is solid, but build/CI pipeline has reliability and security gaps
- Score reflects well-structured runtime implementation with proper error handling, but notable issues in the build pipeline: missing checksum verification for binary downloads creates a security vulnerability, and lack of cache validation could cause CI failures. The core iOS TTS functionality mirrors the proven desktop implementation and should work correctly once built.
- Pay close attention to
setup-ios-onnxruntime.sh(security),build.rs(validation), and both workflow files (cache reliability)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 3/5 | Downloads ONNX Runtime xcframework from HuggingFace but lacks checksum verification, posing a security risk |
| frontend/src-tauri/build.rs | 4/5 | iOS linker configuration for ONNX Runtime. Target detection logic is correct, but missing validation that xcframework exists before build |
| frontend/src-tauri/src/tts.rs | 4/5 | Adds iOS-specific path handling using HOME/Documents directory. Implementation is functional but could benefit from using Tauri's filesystem APIs |
| .github/workflows/mobile-build.yml | 4/5 | Adds ONNX Runtime download and caching for iOS builds. Missing validation step for cached files could lead to broken builds |
| .github/workflows/testflight-on-comment.yml | 4/5 | Adds ONNX Runtime download and caching for TestFlight builds. Same cache validation issue as mobile-build.yml |
Sequence Diagram
sequenceDiagram
participant User
participant TTSContext as TTSContext.tsx
participant Backend as Rust Backend
participant Models as Model Storage
participant ONNX as ONNX Runtime
Note over User,ONNX: iOS TTS Initialization Flow
User->>TTSContext: App starts on iOS
TTSContext->>TTSContext: Detect platform (isTauri() && isIOS())
TTSContext->>Backend: invoke('tts_get_status')
Backend->>Models: Check if models exist in ~/Documents/tts_models
Models-->>Backend: models_downloaded: false
Backend-->>TTSContext: Status: not_downloaded
Note over User,ONNX: Model Download Flow
User->>TTSContext: Trigger download
TTSContext->>Backend: invoke('tts_download_models')
Backend->>Models: Download from HuggingFace (with SHA256 verification)
Models-->>Backend: Models saved to ~/Documents/tts_models
Backend-->>TTSContext: emit('tts-download-progress')
TTSContext->>Backend: invoke('tts_load_models')
Backend->>Models: Load ONNX models
Backend->>ONNX: Initialize sessions (duration_predictor, text_encoder, etc.)
ONNX-->>Backend: Sessions ready
Backend-->>TTSContext: Status: ready
Note over User,ONNX: TTS Synthesis Flow
User->>TTSContext: speak(text, messageId)
TTSContext->>TTSContext: preprocess text (remove code blocks, think tags)
TTSContext->>Backend: invoke('tts_synthesize', {text})
Backend->>Backend: Chunk text (max 300 chars)
Backend->>ONNX: Run inference pipeline
ONNX->>ONNX: Text encoding → Duration prediction → Denoising → Vocoder
ONNX-->>Backend: Audio samples (f32[])
Backend->>Backend: Convert to WAV and Base64 encode
Backend-->>TTSContext: {audio_base64, sample_rate}
TTSContext->>TTSContext: Decode Base64 → AudioContext → Play
TTSContext-->>User: Audio playback
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done | ||
|
|
||
| echo "Downloading iOS arm64 static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
Security: Downloads from HuggingFace lack integrity verification. Unlike the Rust tts_download_models function (tts.rs lines 832-889) which verifies SHA256 checksums, this script downloads and trusts binary files without any verification. Consider adding checksum validation to prevent supply chain attacks.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 52:67
Comment:
Security: Downloads from HuggingFace lack integrity verification. Unlike the Rust `tts_download_models` function (tts.rs lines 832-889) which verifies SHA256 checksums, this script downloads and trusts binary files without any verification. Consider adding checksum validation to prevent supply chain attacks.
How can I resolve this? If you propose a fix, please make it concise.| - name: Cache ONNX Runtime iOS xcframework | ||
| uses: actions/cache@v4 | ||
| id: cache-onnxruntime | ||
| with: | ||
| path: frontend/src-tauri/onnxruntime-ios | ||
| key: onnxruntime-ios-1.20.1 | ||
| restore-keys: | | ||
| onnxruntime-ios- | ||
|
|
||
| - name: Download ONNX Runtime for iOS | ||
| if: steps.cache-onnxruntime.outputs.cache-hit != 'true' | ||
| working-directory: ./frontend/src-tauri | ||
| run: | | ||
| chmod +x scripts/setup-ios-onnxruntime.sh | ||
| ./scripts/setup-ios-onnxruntime.sh |
There was a problem hiding this comment.
Cache validation: No verification that cached xcframework is complete/valid. If a previous build cached a partial download, subsequent builds will use the broken cache without detection. Consider adding a validation step after cache restore (e.g., check file sizes or presence of key files).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 56:70
Comment:
Cache validation: No verification that cached xcframework is complete/valid. If a previous build cached a partial download, subsequent builds will use the broken cache without detection. Consider adding a validation step after cache restore (e.g., check file sizes or presence of key files).
How can I resolve this? If you propose a fix, please make it concise.| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | ||
| let ort_dir = format!("{}/onnxruntime-ios", manifest_dir); | ||
|
|
||
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | ||
| } else { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) | ||
| }; |
There was a problem hiding this comment.
Missing validation: No check if xcframework exists before setting linker flags. If download step fails silently or is skipped, the build fails with cryptic linker errors. Consider adding a check with a helpful error message:
let ort_dir = format!("{}/onnxruntime-ios", manifest_dir);
let xcframework_path = format!("{}/onnxruntime.xcframework", ort_dir);
if !std::path::Path::new(&xcframework_path).exists() {
panic!("ONNX Runtime xcframework not found at {}. Run scripts/setup-ios-onnxruntime.sh first.", xcframework_path);
}Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 6:15
Comment:
Missing validation: No check if xcframework exists before setting linker flags. If download step fails silently or is skipped, the build fails with cryptic linker errors. Consider adding a check with a helpful error message:
```rust
let ort_dir = format!("{}/onnxruntime-ios", manifest_dir);
let xcframework_path = format!("{}/onnxruntime.xcframework", ort_dir);
if !std::path::Path::new(&xcframework_path).exists() {
panic!("ONNX Runtime xcframework not found at {}. Run scripts/setup-ios-onnxruntime.sh first.", xcframework_path);
}
```
How can I resolve this? If you propose a fix, please make it concise.| fn get_tts_models_dir() -> Result<PathBuf> { | ||
| let data_dir = dirs::data_local_dir() | ||
| .context("Failed to get local data directory")? | ||
| .join("cloud.opensecret.maple") | ||
| .join("tts_models"); | ||
| Ok(data_dir) | ||
| // On iOS, we need to use a different approach since dirs::data_local_dir() may not work | ||
| #[cfg(target_os = "ios")] | ||
| { | ||
| // On iOS, use the app's Documents directory which is accessible and persists | ||
| // NSHomeDirectory() + /Documents/tts_models | ||
| let home = std::env::var("HOME").context("Failed to get HOME directory on iOS")?; | ||
| let data_dir = PathBuf::from(home).join("Documents").join("tts_models"); | ||
| return Ok(data_dir); | ||
| } |
There was a problem hiding this comment.
Consider using tauri-plugin-fs for cross-platform path handling. While $HOME/Documents works for iOS sandboxed apps, using Tauri's filesystem plugin would be more consistent with the rest of the app and provide better error messages if the directory is inaccessible.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/tts.rs
Line: 614:623
Comment:
Consider using `tauri-plugin-fs` for cross-platform path handling. While `$HOME/Documents` works for iOS sandboxed apps, using Tauri's filesystem plugin would be more consistent with the rest of the app and provide better error messages if the directory is inaccessible.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| - name: Cache ONNX Runtime iOS xcframework | ||
| uses: actions/cache@v4 | ||
| id: cache-onnxruntime | ||
| with: | ||
| path: frontend/src-tauri/onnxruntime-ios | ||
| key: onnxruntime-ios-1.20.1 | ||
| restore-keys: | | ||
| onnxruntime-ios- | ||
|
|
||
| - name: Download ONNX Runtime for iOS | ||
| if: steps.cache-onnxruntime.outputs.cache-hit != 'true' | ||
| working-directory: ./frontend/src-tauri | ||
| run: | | ||
| chmod +x scripts/setup-ios-onnxruntime.sh | ||
| ./scripts/setup-ios-onnxruntime.sh |
There was a problem hiding this comment.
Cache validation: No verification that cached xcframework is complete/valid. If a previous build cached a partial download, subsequent builds will use the broken cache without detection. Consider adding a validation step after cache restore (e.g., check file sizes or presence of key files).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 114:128
Comment:
Cache validation: No verification that cached xcframework is complete/valid. If a previous build cached a partial download, subsequent builds will use the broken cache without detection. Consider adding a validation step after cache restore (e.g., check file sizes or presence of key files).
How can I resolve this? If you propose a fix, please make it concise.- Add iOS-specific ort dependencies in Cargo.toml - Update build.rs to link ONNX Runtime xcframework for iOS - Enable TTS module for iOS in lib.rs (was desktop-only) - Add iOS-specific path handling in tts.rs for model storage - Update TTSContext.tsx to enable TTS on iOS - Add setup-ios-onnxruntime.sh script to download pre-built xcframework - Update GitHub Actions workflows to download ONNX Runtime before iOS builds - Add onnxruntime-ios/ to .gitignore Uses pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace (csukuangfj/ios-onnxruntime) for static linking on iOS. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The ort crate requires the ndarray feature to be explicitly enabled when default-features = false. This fixes the iOS build by enabling the ndarray feature which provides OwnedTensorArrayData trait implementations for ndarray types. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The ort crate requires the 'std' feature for: 1. ort::Error to implement std::error::Error (StdError trait) 2. commit_from_file method for loading ONNX models from filesystem Without 'std', the ? operator cannot convert ort::Error to anyhow::Error and file-based session loading is unavailable. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The ort-sys crate needs ORT_LIB_LOCATION environment variable set before cargo build starts to locate the ONNX Runtime static library. Setting it in build.rs doesn't work because ort-sys checks for the library during its own build process. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech (TTS) support for iOS using ONNX Runtime, enabling the Supertonic TTS model to run on-device. The implementation mirrors the existing desktop TTS functionality and involves changes across build configuration, runtime initialization, and frontend platform detection.
Key Changes
Build Infrastructure:
- Adds a download script (
setup-ios-onnxruntime.sh) to fetch pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace - Configures GitHub Actions workflows to cache and setup ONNX Runtime before iOS builds
- Adds iOS-specific linker configuration in
build.rsto link the static ONNX Runtime library
Runtime Configuration:
- Enables the TTS module for iOS (previously desktop-only) with conditional compilation
- Adds TTS state management and command handlers to the iOS-specific app configuration
- Updates iOS storage path to use
~/Documents/tts_modelsinstead of standard app data directory
Frontend Integration:
- Updates
TTSContext.tsxto enable TTS on iOS by checkingisTauri() && isIOS() - Maintains the same user-facing behavior: users download models on-demand (~264MB)
Architecture
The implementation follows the existing desktop TTS pattern:
- ONNX Runtime xcframework is downloaded at build time and cached
- TTS models are downloaded by users at runtime on first use
- Models are loaded into memory and used for on-device synthesis
- Same Supertonic model used across desktop and iOS for consistency
Issues Identified
The implementation has several issues that need to be addressed:
-
Critical: Incorrect ORT_LIB_LOCATION path - Both GitHub Actions workflows set the environment variable to point to a subdirectory instead of the base directory, which conflicts with how build.rs expects it
-
Security: Missing checksum verification - The setup script downloads large binary files without verifying their integrity, unlike the TTS model downloads which include SHA256 verification
-
Robustness: No directory existence check - The build script doesn't verify the ONNX Runtime directory exists, leading to cryptic linker errors if setup fails
-
Reliability: HOME environment variable usage - iOS path handling relies on the HOME env var which may not be reliable in all iOS contexts (sandboxed apps, extensions)
Confidence Score: 2/5
- This PR has critical configuration issues that will likely cause build failures and security concerns
- Score reflects two critical issues: (1) ORT_LIB_LOCATION path mismatch will cause builds to fail or link incorrectly, and (2) missing checksum verification for downloaded binaries creates security risk. The setup script downloads ~100MB+ of unverified binary code from HuggingFace. Additional robustness issues include lack of build-time directory checks and questionable iOS path handling.
- Pay close attention to .github/workflows/mobile-build.yml and testflight-on-comment.yml (ORT_LIB_LOCATION paths must be fixed), frontend/src-tauri/scripts/setup-ios-onnxruntime.sh (needs checksum verification), and frontend/src-tauri/build.rs (needs existence check)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 3/5 | Adds ONNX Runtime caching and setup for iOS builds, but ORT_LIB_LOCATION path is incorrect |
| .github/workflows/testflight-on-comment.yml | 3/5 | Adds ONNX Runtime caching and setup for TestFlight builds, same ORT_LIB_LOCATION path issue |
| frontend/src-tauri/build.rs | 3/5 | Adds iOS linker configuration for ONNX Runtime, but lacks directory existence check |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 2/5 | Downloads ONNX Runtime xcframework for iOS, but missing checksum verification for downloaded files |
| frontend/src-tauri/src/lib.rs | 4/5 | Enables TTS module for iOS, adds TTS commands to iOS invoke handler and state management |
| frontend/src-tauri/src/tts.rs | 3/5 | Adds iOS-specific path handling using HOME env var, which may not be reliable in all contexts |
Sequence Diagram
sequenceDiagram
participant User
participant Frontend as TTSContext (Frontend)
participant Tauri as Tauri Runtime
participant TTS as TTS Module (Rust)
participant FS as File System
participant ONNX as ONNX Runtime
participant HF as HuggingFace
Note over User,HF: Build Time Setup
User->>Tauri: Trigger iOS Build
Tauri->>FS: Check onnxruntime-ios cache
alt Cache Miss
Tauri->>HF: Download xcframework (setup-ios-onnxruntime.sh)
HF-->>FS: ONNX Runtime binaries (~100MB)
Note over FS: No checksum verification ⚠️
end
Tauri->>ONNX: Link static library (build.rs)
Note over ONNX: ORT_LIB_LOCATION path issue ⚠️
Note over User,HF: Runtime - First Use
User->>Frontend: Enable TTS
Frontend->>Tauri: tts_get_status()
Tauri->>TTS: Check models
TTS->>FS: Check ~/Documents/tts_models
Note over FS: HOME env var usage ⚠️
TTS-->>Frontend: models_downloaded=false
User->>Frontend: Download Models
Frontend->>Tauri: tts_download_models()
Tauri->>TTS: Download from HuggingFace
loop For each model file
TTS->>HF: Download model
HF-->>TTS: Model data
TTS->>TTS: Verify SHA256 checksum
TTS->>FS: Save to ~/Documents/tts_models
TTS-->>Frontend: Progress event
end
Frontend->>Tauri: tts_load_models()
Tauri->>TTS: Load models
TTS->>FS: Read model files
TTS->>ONNX: Create ONNX sessions
ONNX-->>TTS: Sessions ready
TTS-->>Frontend: Models loaded
Note over User,HF: Runtime - Synthesis
User->>Frontend: Click speak button
Frontend->>Tauri: tts_synthesize(text)
Tauri->>TTS: Synthesize
TTS->>TTS: Preprocess text
TTS->>ONNX: Run inference (4 models)
ONNX-->>TTS: Audio samples
TTS->>TTS: Encode to WAV + base64
TTS-->>Frontend: audio_base64
Frontend->>Frontend: Decode & play via Web Audio API
| VITE_MAPLE_BILLING_API_URL: https://billing.opensecret.cloud | ||
| VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6 | ||
| # ONNX Runtime location for ort-sys crate | ||
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 |
There was a problem hiding this comment.
The ORT_LIB_LOCATION path is incorrect. According to the build.rs file (line 26), ORT_LIB_LOCATION should point to the onnxruntime-ios directory, not to the ios-arm64 subdirectory within the xcframework.
The build.rs sets ORT_LIB_LOCATION={ort_dir} where ort_dir = "{manifest_dir}/onnxruntime-ios", and then constructs the lib_path by appending the appropriate xcframework subdirectory based on the target.
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 | |
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 109:109
Comment:
The `ORT_LIB_LOCATION` path is incorrect. According to the build.rs file (line 26), `ORT_LIB_LOCATION` should point to the `onnxruntime-ios` directory, not to the `ios-arm64` subdirectory within the xcframework.
The build.rs sets `ORT_LIB_LOCATION={ort_dir}` where `ort_dir = "{manifest_dir}/onnxruntime-ios"`, and then constructs the lib_path by appending the appropriate xcframework subdirectory based on the target.
```suggestion
ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios
```
How can I resolve this? If you propose a fix, please make it concise.| VITE_MAPLE_BILLING_API_URL: https://billing.opensecret.cloud | ||
| VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6 | ||
| # ONNX Runtime location for ort-sys crate | ||
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 |
There was a problem hiding this comment.
The ORT_LIB_LOCATION path is incorrect - same issue as in mobile-build.yml. According to the build.rs file (line 26), ORT_LIB_LOCATION should point to the onnxruntime-ios directory, not to the ios-arm64 subdirectory within the xcframework.
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 | |
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 167:167
Comment:
The `ORT_LIB_LOCATION` path is incorrect - same issue as in mobile-build.yml. According to the build.rs file (line 26), `ORT_LIB_LOCATION` should point to the `onnxruntime-ios` directory, not to the `ios-arm64` subdirectory within the xcframework.
```suggestion
ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios
```
How can I resolve this? If you propose a fix, please make it concise.| echo "Downloading Info.plist..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done | ||
|
|
||
| echo "Downloading iOS arm64 static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
The downloaded ONNX Runtime files are not verified with checksums before use. This creates a security risk as corrupted or tampered files could be used without detection. The TTS model downloads (in tts.rs) include SHA256 verification - the same approach should be used here.
Consider adding checksum verification similar to the TTS model downloads:
echo "Downloading iOS arm64 static library..."
curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a"
# Verify checksum
EXPECTED_SHA256="<expected_hash_here>"
ACTUAL_SHA256=$(shasum -a 256 "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" | awk '{print $1}')
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
echo "Error: Checksum mismatch for ios-arm64/onnxruntime.a"
exit 1
fiPrompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 51:67
Comment:
The downloaded ONNX Runtime files are not verified with checksums before use. This creates a security risk as corrupted or tampered files could be used without detection. The TTS model downloads (in tts.rs) include SHA256 verification - the same approach should be used here.
Consider adding checksum verification similar to the TTS model downloads:
```bash
echo "Downloading iOS arm64 static library..."
curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a"
# Verify checksum
EXPECTED_SHA256="<expected_hash_here>"
ACTUAL_SHA256=$(shasum -a 256 "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" | awk '{print $1}')
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
echo "Error: Checksum mismatch for ios-arm64/onnxruntime.a"
exit 1
fi
```
How can I resolve this? If you propose a fix, please make it concise.| #[cfg(target_os = "ios")] | ||
| { | ||
| // Get the path to the ONNX Runtime xcframework | ||
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | ||
| let ort_dir = format!("{}/onnxruntime-ios", manifest_dir); | ||
|
|
||
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | ||
| } else { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) | ||
| }; |
There was a problem hiding this comment.
The build script doesn't verify that the ONNX Runtime directory exists before attempting to use it. If the setup script fails or hasn't been run, this will cause cryptic linker errors that are difficult to debug.
Consider adding a check with a helpful error message:
| #[cfg(target_os = "ios")] | |
| { | |
| // Get the path to the ONNX Runtime xcframework | |
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | |
| let ort_dir = format!("{}/onnxruntime-ios", manifest_dir); | |
| // Check if building for simulator or device | |
| let target = std::env::var("TARGET").unwrap_or_default(); | |
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | |
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| } else { | |
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) | |
| }; | |
| #[cfg(target_os = "ios")] | |
| { | |
| // Get the path to the ONNX Runtime xcframework | |
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | |
| let ort_dir = format!("{}/onnxruntime-ios", manifest_dir); | |
| // Verify the xcframework exists before proceeding | |
| let xcframework_path = format!("{}/onnxruntime.xcframework", ort_dir); | |
| if !std::path::Path::new(&xcframework_path).exists() { | |
| panic!( | |
| "ONNX Runtime xcframework not found at: {}\n\ | |
| Please run: ./scripts/setup-ios-onnxruntime.sh", | |
| xcframework_path | |
| ); | |
| } | |
| // Check if building for simulator or device | |
| let target = std::env::var("TARGET").unwrap_or_default(); | |
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | |
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| } else { | |
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) | |
| }; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 3:15
Comment:
The build script doesn't verify that the ONNX Runtime directory exists before attempting to use it. If the setup script fails or hasn't been run, this will cause cryptic linker errors that are difficult to debug.
Consider adding a check with a helpful error message:
```suggestion
#[cfg(target_os = "ios")]
{
// Get the path to the ONNX Runtime xcframework
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
let ort_dir = format!("{}/onnxruntime-ios", manifest_dir);
// Verify the xcframework exists before proceeding
let xcframework_path = format!("{}/onnxruntime.xcframework", ort_dir);
if !std::path::Path::new(&xcframework_path).exists() {
panic!(
"ONNX Runtime xcframework not found at: {}\n\
Please run: ./scripts/setup-ios-onnxruntime.sh",
xcframework_path
);
}
// Check if building for simulator or device
let target = std::env::var("TARGET").unwrap_or_default();
let lib_path = if target.contains("sim") || target.contains("x86_64") {
format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir)
} else {
format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir)
};
```
How can I resolve this? If you propose a fix, please make it concise.| #[cfg(target_os = "ios")] | ||
| { | ||
| // On iOS, use the app's Documents directory which is accessible and persists | ||
| // NSHomeDirectory() + /Documents/tts_models | ||
| let home = std::env::var("HOME").context("Failed to get HOME directory on iOS")?; | ||
| let data_dir = PathBuf::from(home).join("Documents").join("tts_models"); | ||
| return Ok(data_dir); | ||
| } |
There was a problem hiding this comment.
Using std::env::var("HOME") on iOS may not be reliable in all contexts (sandboxed apps, different iOS versions, app extensions). Consider using Tauri's path APIs or iOS-specific APIs to get the documents directory more reliably.
For example, you could use Tauri's app_data_dir() or app_document_dir() functions which properly handle iOS sandboxing and provide the correct paths for the application's data storage.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/tts.rs
Line: 616:623
Comment:
Using `std::env::var("HOME")` on iOS may not be reliable in all contexts (sandboxed apps, different iOS versions, app extensions). Consider using Tauri's path APIs or iOS-specific APIs to get the documents directory more reliably.
For example, you could use Tauri's `app_data_dir()` or `app_document_dir()` functions which properly handle iOS sandboxing and provide the correct paths for the application's data storage.
How can I resolve this? If you propose a fix, please make it concise.The ort-sys crate expects the static library to be named 'libonnxruntime.a' (with the 'lib' prefix), not 'onnxruntime.a'. Also adds verification step to debug library location and invalidates cache to force re-download. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2cfa212 to
a617282
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @frontend/src-tauri/Cargo.toml:
- Around line 56-71: The Cargo.toml currently pins the ONNX Runtime crate as ort
= "2.0.0-rc.10" (pre-release); replace this with a stable ort version (e.g., the
latest 1.x stable) or, if 2.0.0-rc.10 is required for iOS support, add a comment
documenting the exact compatibility reason and link to the upstream release
notes; update the ort entry in the target.'cfg(target_os = "ios")'.dependencies
block accordingly and ensure feature flags (["std","ndarray"]) remain correct
for the chosen stable version.
🧹 Nitpick comments (2)
frontend/src/services/tts/TTSContext.tsx (1)
63-64: Consider simplifying the iOS detection logic.The logic correctly extends TTS availability to iOS, but the condition could be slightly cleaner. Since
isTauriDesktop()likely already checksisTauri(), the explicitisTauri()check in the iOS condition may be redundant depending on the implementation of these utility functions.♻️ Optional simplification
If
isTauriDesktop()already ensures it's a Tauri environment, you could simplify to:- // Check Tauri environment - TTS is available on desktop and iOS (not Android) - const isTauriEnv = isTauriDesktop() || (isTauri() && isIOS()); + // Check Tauri environment - TTS is available on desktop and iOS (not Android) + const isTauriEnv = isTauriDesktop() || isIOS();However, only apply this if
isIOS()is guaranteed to be used within a Tauri context. The current implementation is safe and explicit, so this is purely optional.frontend/src-tauri/src/lib.rs (1)
269-317: Consider reducing code duplication between iOS and Android setup blocks.The iOS and Android configuration blocks contain significant duplication, particularly in the setup closures (lines 275-288 vs 303-316). The deep link handler registration is identical in both blocks.
♻️ Suggested refactor to reduce duplication
Consider extracting the common setup logic into a shared function:
// Add before the cfg blocks #[cfg(not(desktop))] fn setup_mobile_deep_link_handler(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> { let app_handle = app.handle().clone(); // Register deep link handler - note that iOS does not support runtime registration // but the handler for incoming URLs still works app.deep_link().on_open_url(move |event| { if let Some(url) = event.urls().first() { handle_deep_link_event(url.as_ref(), &app_handle); } }); Ok(()) }Then simplify both blocks:
// Android-specific configuration (no TTS) #[cfg(all(not(desktop), target_os = "android"))] let app = builder .invoke_handler(tauri::generate_handler![ pdf_extractor::extract_document_content, ]) .setup(|app| setup_mobile_deep_link_handler(app)) .plugin(tauri_plugin_updater::Builder::new().build()); // iOS-specific configuration (with TTS) #[cfg(all(not(desktop), target_os = "ios"))] let app = builder .invoke_handler(tauri::generate_handler![ pdf_extractor::extract_document_content, tts::tts_get_status, tts::tts_download_models, tts::tts_load_models, tts::tts_synthesize, tts::tts_unload_models, tts::tts_delete_models, ]) .setup(|app| setup_mobile_deep_link_handler(app)) .plugin(tauri_plugin_updater::Builder::new().build());This reduces duplication and makes the code easier to maintain.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.ymlfrontend/src-tauri/.gitignorefrontend/src-tauri/Cargo.tomlfrontend/src-tauri/build.rsfrontend/src-tauri/scripts/setup-ios-onnxruntime.shfrontend/src-tauri/src/lib.rsfrontend/src-tauri/src/tts.rsfrontend/src/services/tts/TTSContext.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
- frontend/src-tauri/src/tts.rs
- frontend/src-tauri/.gitignore
- frontend/src-tauri/build.rs
- frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
- .github/workflows/mobile-build.yml
- .github/workflows/testflight-on-comment.yml
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use path aliases (@/*maps to./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid usinganytype
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Runjust format,just lint, andjust buildafter making TypeScript/React changes to ensure code quality and compilation
Files:
frontend/src/services/tts/TTSContext.tsx
🧠 Learnings (2)
📚 Learning: 2025-03-25T19:50:07.925Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 23
File: frontend/src-tauri/src/lib.rs:14-16
Timestamp: 2025-03-25T19:50:07.925Z
Learning: In Tauri applications, updater security configurations (including endpoints, public key for verification, and dialog settings) should be defined in the tauri.conf.json file rather than duplicated in the code. When initialized with tauri_plugin_updater::Builder::new().build(), the plugin automatically reads and uses these settings from the configuration file.
Applied to files:
frontend/src-tauri/src/lib.rs
📚 Learning: 2025-03-25T19:50:07.925Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 23
File: frontend/src-tauri/src/lib.rs:14-16
Timestamp: 2025-03-25T19:50:07.925Z
Learning: In Tauri applications, the updater configuration (including security settings like server URL and public key) should be defined in tauri.conf.json rather than hardcoded in the application code. The code only needs to initialize the updater plugin with tauri_plugin_updater::Builder::new().build(), which will automatically use the settings from the configuration file.
Applied to files:
frontend/src-tauri/src/lib.rs
🧬 Code graph analysis (1)
frontend/src-tauri/src/lib.rs (1)
frontend/src-tauri/src/tts.rs (8)
new(174-176)new(451-456)tts_get_status(735-757)tts_download_models(768-899)tts_load_models(902-920)tts_synthesize(930-972)tts_unload_models(975-981)tts_delete_models(984-1000)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-linux
- GitHub Check: build-ios
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-android
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
frontend/src/services/tts/TTSContext.tsx (1)
10-10: LGTM: Clean import additions for iOS support.The added imports (
isIOS,isTauri) are necessary for the iOS platform detection logic below and follow the established path alias pattern.frontend/src-tauri/src/lib.rs (3)
6-8: LGTM: TTS module correctly extended to iOS.The conditional compilation correctly enables the TTS module for both desktop and iOS platforms, with a clear comment explaining the availability.
244-255: LGTM: Clean mobile configuration setup.The base mobile builder configuration is properly shared between iOS and Android platforms, with appropriate plugin initialization.
263-267: LGTM: iOS TTS state management correctly initialized.The TTS state is properly initialized for iOS builds using the same pattern as desktop, with appropriate conditional compilation.
| [target.'cfg(target_os = "ios")'.dependencies] | ||
| # TTS dependencies (Supertonic) - iOS | ||
| # Uses pre-built ONNX Runtime xcframework from HuggingFace | ||
| # We disable download-binaries and copy-dylibs since we link our own xcframework | ||
| # Need "std" for Error trait impl and file operations, "ndarray" for tensor creation | ||
| ort = { version = "2.0.0-rc.10", default-features = false, features = ["std", "ndarray"] } | ||
| ndarray = { version = "0.16" } | ||
| rand = "0.8" | ||
| rand_distr = "0.4" | ||
| hound = "3.5" | ||
| unicode-normalization = "0.1" | ||
| regex = "1.10" | ||
| reqwest = { version = "0.12", features = ["stream"] } | ||
| futures-util = "0.3" | ||
| dirs = "5.0" | ||
| sha2 = "0.10" |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
ONNX Runtime 2.0.0-rc.10 release status production iOS
💡 Result:
Short answer: 2.0.0-rc.10 is a release-candidate (pre-release), not a GA release—so it’s not recommended as a drop-in production build for iOS without your own validation and testing. The ort 2.0.0-rc.10 Rust wrapper exists, and ONNX Runtime provides iOS build instructions and supported iOS platforms, but RCs can contain breaking changes or unresolved bugs and should be treated as test/pre‑production. [1][2]
References
- ort 2.0.0-rc.10 (crate documentation). [1]
- ONNX Runtime iOS build & platform support (instructions and supported iOS architectures). [2]
🌐 Web query:
ONNX Runtime latest stable version iOS support
💡 Result:
As of Jan 9, 2026 the latest stable ONNX Runtime release is 1.23.2 (released Oct 2025). It supports iOS (arm64 devices and x86_64 simulator); the docs list iOS 12 as the tested minimum and note tvOS/watchOS and 32-bit architectures are not supported. [1][2]
Sources:
- ONNX Runtime roadmap / release announcement. [1]
- ONNX Runtime iOS build documentation (platforms, architectures, minimum tested iOS). [2]
🌐 Web query:
ONNX Runtime 2.0.0 final release iOS xcframework
💡 Result:
Short answer: There is no ONNX Runtime "2.0.0 final" release or official iOS xcframework available (ONNX Runtime releases are still in the 1.x series). See the official releases page and the iOS build docs. [1][2]
If you need an iOS xcframework now, you can either:
- build an iOS xcframework from the ONNX Runtime repo using the iOS build scripts (instructions here). [1]
- or use the latest official release assets from the ONNX Runtime GitHub Releases page (download binaries or source and build an xcframework). [2]
References
- Build ONNX Runtime for iOS (instructions). [1]
- ONNX Runtime releases / GitHub (official releases page). [2]
Would you like step-by-step commands to build an iOS xcframework from the current ONNX Runtime release?
Replace ONNX Runtime release candidate with a stable version.
Using ort = "2.0.0-rc.10" (a pre-release) in production is not recommended. ONNX Runtime 2.0.0 has not reached a stable release—the latest stable version is 1.23.2 (Oct 2025), which supports iOS with arm64 devices and x86_64 simulator. Release candidates can contain breaking changes or unresolved bugs.
Either upgrade to the latest stable release or document the specific reason this RC version is necessary for iOS compatibility.
🤖 Prompt for AI Agents
In @frontend/src-tauri/Cargo.toml around lines 56 - 71, The Cargo.toml currently
pins the ONNX Runtime crate as ort = "2.0.0-rc.10" (pre-release); replace this
with a stable ort version (e.g., the latest 1.x stable) or, if 2.0.0-rc.10 is
required for iOS support, add a comment documenting the exact compatibility
reason and link to the upstream release notes; update the ort entry in the
target.'cfg(target_os = "ios")'.dependencies block accordingly and ensure
feature flags (["std","ndarray"]) remain correct for the chosen stable version.
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
iOS TTS Support Implementation
This PR adds Text-to-Speech functionality to iOS by integrating ONNX Runtime 1.20.1 through a pre-built xcframework from HuggingFace. The implementation mirrors the existing desktop TTS architecture and enables on-device TTS synthesis using the Supertonic model.
What Changed
- Build System: Added iOS-specific build configuration in
build.rsto link ONNX Runtime static libraries and iOS frameworks - Dependencies: Added iOS-specific Cargo.toml targets with properly configured
ortcrate (disabling default features, enabling std/ndarray only) - Runtime Code: Modified
lib.rsto enable TTS module on iOS, added conditional iOS invoke handlers for TTS commands - Model Storage: Updated
tts.rsto use~/Documents/tts_modelspath on iOS (sandboxed app directory) instead of desktop paths - Frontend: Updated
TTSContext.tsxplatform detection to enable TTS on both desktop and iOS - CI/CD: Added cache and download steps in both mobile-build and testflight workflows, with ORT_LIB_LOCATION environment variable
Architecture
The implementation properly separates platform-specific code:
- Desktop (macos/linux/windows): Uses full-featured ort with rayon parallelization
- iOS: Uses stripped-down ort (std, ndarray only) with pre-linked xcframework
- Android: TTS explicitly disabled (no changes to existing Android support)
Issues Found
Critical (Blocks Merge):
- build.rs: Unprotected
unwrap()on CARGO_MANIFEST_DIR and missing library file existence check - setup-ios-onnxruntime.sh: No SHA256 checksum verification for downloaded binaries - security vulnerability
- setup-ios-onnxruntime.sh: curl commands don't validate HTTP status codes, allowing silent download failures
- setup-ios-onnxruntime.sh: Large binary downloads lack timeout settings, risk of indefinite build hangs
Important (Should Fix):
- build.rs: No verification that onnxruntime directory exists during build
- Workflows: Verification step silently fails, masking missing ONNX Runtime files with unclear downstream errors
- setup-ios-onnxruntime.sh: No timeout protection on curl requests for ~100MB downloads
Minor (Nice to Have):
- Documentation on how to manually set up iOS builds when GitHub cache is unavailable
Risk Assessment
- Build Reliability: Currently fragile - silent failures in setup script will cause confusing linker errors
- Security: Binary downloads lack integrity verification, vulnerable to supply chain attacks
- Maintainability: Hard-coded paths and versions make future updates difficult
The core TTS implementation is sound, but the build infrastructure needs hardening before production use.
Confidence Score: 2/5
- This PR should not be merged in current form - it has critical build reliability and security issues that must be fixed.
- Score of 2 reflects serious blockers: (1) build.rs uses unwrap() without proper error handling, (2) setup script downloads binaries without checksum verification (security vulnerability), (3) missing HTTP error checks on curl (silent failures), (4) no existence verification before linking. These issues will cause difficult-to-debug build failures and security risks. The TTS implementation itself is solid (4-5 confidence), but infrastructure issues prevent safe deployment.
- Critical attention needed: frontend/src-tauri/build.rs, frontend/src-tauri/scripts/setup-ios-onnxruntime.sh. High attention: .github/workflows/mobile-build.yml, .github/workflows/testflight-on-comment.yml
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/build.rs | 2/5 | iOS build configuration has critical issues: uses unwrap() without error handling, doesn't verify required library files exist before linking, leading to unclear build failure messages if setup fails. |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 2/5 | Critical security and reliability issues: downloads binary files without checksum verification, no HTTP error checking on curl, no timeout settings for large downloads, vulnerable to MITM attacks and silent failures. |
| .github/workflows/mobile-build.yml | 3/5 | Workflow verification step runs even after download failures, silently ignoring missing critical files and leading to confusing downstream build errors. |
| frontend/src-tauri/src/tts.rs | 4/5 | Good implementation with proper iOS path handling. Model download and TTS synthesis logic is sound with appropriate error handling. |
| frontend/src-tauri/src/lib.rs | 4/5 | iOS and Android configurations properly separated with correct conditional compilation. TTS commands correctly registered for iOS only. |
Sequence Diagram
sequenceDiagram
participant Build as GitHub Actions
participant Script as setup-ios-onnxruntime.sh
participant HF as HuggingFace
participant BuildRs as build.rs
participant Cargo as Cargo Build
participant App as iOS App
Note over Build,App: Build Phase
Build->>Script: Run setup script
Script->>HF: Download onnxruntime.xcframework
HF-->>Script: Binary files
Script->>Script: Extract and organize
Note over Build,App: Compilation Phase
Build->>BuildRs: Execute build.rs
BuildRs->>BuildRs: Check TARGET (device/sim)
BuildRs->>BuildRs: Set link paths
BuildRs->>Cargo: Provide ORT_LIB_LOCATION
Note over Build,App: Linking Phase
Cargo->>Cargo: Link onnxruntime static lib
Cargo->>Cargo: Link iOS frameworks
Cargo-->>Build: iOS app binary
Note over Build,App: Runtime Phase
App->>App: Initialize TTS module on iOS
App->>App: Get models dir (~/Documents/tts_models)
App->>App: Download models from HuggingFace (if needed)
App->>App: Load ONNX Runtime session
App->>App: Ready for TTS synthesis
| #[cfg(target_os = "ios")] | ||
| { | ||
| // Get the path to the ONNX Runtime xcframework | ||
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); |
There was a problem hiding this comment.
The unwrap() call on line 6 will panic if CARGO_MANIFEST_DIR is not set. This is a build-time failure that will cause confusing error messages. Should use expect() with a descriptive message or handle the error gracefully.
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | |
| let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set - this is required by Cargo"); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 6:6
Comment:
The `unwrap()` call on line 6 will panic if `CARGO_MANIFEST_DIR` is not set. This is a build-time failure that will cause confusing error messages. Should use `expect()` with a descriptive message or handle the error gracefully.
```suggestion
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set - this is required by Cargo");
```
How can I resolve this? If you propose a fix, please make it concise.| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done | ||
|
|
||
| echo "Downloading iOS arm64 static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" | ||
|
|
There was a problem hiding this comment.
The script downloads binary files (libonnxruntime.a) from HuggingFace without any integrity verification (checksums, signatures, or GPG verification). This is a security vulnerability - downloaded binaries could be compromised or tampered with. The PR description mentions pinning to a specific revision for "integrity and reproducibility" in tts.rs but this is NOT implemented here.
Additionally, the script uses curl -L (follow redirects) without validating the final URL, which could expose the build to MITM attacks.
Recommendation: Add SHA256 checksums for all downloaded files and verify them after download:
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading headers..." | |
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | |
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | |
| done | |
| echo "Downloading iOS arm64 static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| echo "Downloading iOS simulator static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" | |
| echo "Downloading Info.plist..." | |
| PLIST_SHA256="expected_hash_here" | |
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "$PLIST_SHA256 $XCFRAMEWORK_DIR/Info.plist" | sha256sum -c - || { echo "Checksum mismatch"; exit 1; } |
Do this for all downloaded files, especially the large binary libraries.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 52:68
Comment:
The script downloads binary files (libonnxruntime.a) from HuggingFace without any integrity verification (checksums, signatures, or GPG verification). This is a security vulnerability - downloaded binaries could be compromised or tampered with. The PR description mentions pinning to a specific revision for "integrity and reproducibility" in tts.rs but this is NOT implemented here.
Additionally, the script uses `curl -L` (follow redirects) without validating the final URL, which could expose the build to MITM attacks.
Recommendation: Add SHA256 checksums for all downloaded files and verify them after download:
```suggestion
echo "Downloading Info.plist..."
PLIST_SHA256="expected_hash_here"
curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist"
echo "$PLIST_SHA256 $XCFRAMEWORK_DIR/Info.plist" | sha256sum -c - || { echo "Checksum mismatch"; exit 1; }
```
Do this for all downloaded files, especially the large binary libraries.
How can I resolve this? If you propose a fix, please make it concise.| @@ -279,6 +288,34 @@ pub fn run() { | |||
| }) | |||
| .plugin(tauri_plugin_updater::Builder::new().build()); | |||
There was a problem hiding this comment.
There is a critical control flow issue: the Android configuration block (lines 269-289) creates the app binding with let app = builder..., but the iOS configuration block (lines 291-317) also tries to create let app = builder... using the SAME builder variable that was already consumed. In Rust, the first branch consumes builder, so the second let app assignment will fail to compile because builder no longer exists.
This appears to be a logic error in the conditional compilation. The code structure should ensure that ONLY ONE of these branches executes (they have mutually exclusive conditions), but both branches are trying to create an app from the same builder. This will cause a compilation error.
Expected fix: Verify that these cfg conditions are truly mutually exclusive and that only one branch will ever execute. If both branches need builder, there's a design issue that needs refactoring.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/lib.rs
Line: 269:289
Comment:
There is a critical control flow issue: the Android configuration block (lines 269-289) creates the `app` binding with `let app = builder...`, but the iOS configuration block (lines 291-317) also tries to create `let app = builder...` using the SAME builder variable that was already consumed. In Rust, the first branch consumes `builder`, so the second `let app` assignment will fail to compile because `builder` no longer exists.
This appears to be a logic error in the conditional compilation. The code structure should ensure that ONLY ONE of these branches executes (they have mutually exclusive conditions), but both branches are trying to create an `app` from the same `builder`. This will cause a compilation error.
Expected fix: Verify that these cfg conditions are truly mutually exclusive and that only one branch will ever execute. If both branches need `builder`, there's a design issue that needs refactoring.
How can I resolve this? If you propose a fix, please make it concise.| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done | ||
|
|
||
| echo "Downloading iOS arm64 static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
The curl commands downloading large binary files (libonnxruntime.a files are ~100MB each) don't have connection or timeout settings. This could cause the build to hang indefinitely if the network is slow or the remote server is unresponsive. Add explicit timeout values to prevent build hangs.
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading headers..." | |
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | |
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | |
| done | |
| echo "Downloading iOS arm64 static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| echo "Downloading iOS simulator static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" | |
| echo "Downloading iOS arm64 static library (this may take a while)..." | |
| curl -L --connect-timeout 30 --max-time 3600 -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| echo "Downloading iOS simulator static library (this may take a while)..." | |
| curl -L --connect-timeout 30 --max-time 3600 -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
Apply similar timeout settings to all curl commands in the script.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 52:67
Comment:
The curl commands downloading large binary files (libonnxruntime.a files are ~100MB each) don't have connection or timeout settings. This could cause the build to hang indefinitely if the network is slow or the remote server is unresponsive. Add explicit timeout values to prevent build hangs.
```suggestion
echo "Downloading iOS arm64 static library (this may take a while)..."
curl -L --connect-timeout 30 --max-time 3600 -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a"
echo "Downloading iOS simulator static library (this may take a while)..."
curl -L --connect-timeout 30 --max-time 3600 -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a"
```
Apply similar timeout settings to all curl commands in the script.
How can I resolve this? If you propose a fix, please make it concise.| // Tell cargo where to find the ONNX Runtime static library | ||
| println!("cargo:rustc-link-search=native={}", lib_path); | ||
| println!("cargo:rustc-link-lib=static=onnxruntime"); |
There was a problem hiding this comment.
The build script tells cargo to link against the ONNX Runtime library without verifying that the path actually exists. If the onnxruntime-ios directory was not downloaded (e.g., the setup script failed silently or was skipped), the build will fail with an obscure linker error rather than a clear error message about the missing file.
Add a check to verify the library exists before proceeding:
| // Tell cargo where to find the ONNX Runtime static library | |
| println!("cargo:rustc-link-search=native={}", lib_path); | |
| println!("cargo:rustc-link-lib=static=onnxruntime"); | |
| // Tell cargo where to find the ONNX Runtime static library | |
| if !std::path::Path::new(&lib_path).exists() { | |
| panic!("ONNX Runtime library not found at {}. Did you run setup-ios-onnxruntime.sh?", lib_path); | |
| } | |
| println!("cargo:rustc-link-search=native={}", lib_path); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 17:19
Comment:
The build script tells cargo to link against the ONNX Runtime library without verifying that the path actually exists. If the `onnxruntime-ios` directory was not downloaded (e.g., the setup script failed silently or was skipped), the build will fail with an obscure linker error rather than a clear error message about the missing file.
Add a check to verify the library exists before proceeding:
```suggestion
// Tell cargo where to find the ONNX Runtime static library
if !std::path::Path::new(&lib_path).exists() {
panic!("ONNX Runtime library not found at {}. Did you run setup-ios-onnxruntime.sh?", lib_path);
}
println!("cargo:rustc-link-search=native={}", lib_path);
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Verify ONNX Runtime files | ||
| run: | | ||
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | ||
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | ||
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" |
There was a problem hiding this comment.
The "Verify ONNX Runtime files" step runs unconditionally, but if the download step failed, this verification will also fail silently (due to the || echo fallback). The build will continue even though critical files are missing, leading to build failure downstream with confusing error messages.
The verification step should explicitly check if the required directory exists and fail the workflow if it doesn't:
| - name: Verify ONNX Runtime files | |
| run: | | |
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" | |
| - name: Verify ONNX Runtime files | |
| run: | | |
| ORT_PATH="${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| if [ ! -f "$ORT_PATH/libonnxruntime.a" ]; then | |
| echo "ERROR: ONNX Runtime library not found at $ORT_PATH/libonnxruntime.a" | |
| exit 1 | |
| fi | |
| echo "ONNX Runtime files verified successfully" | |
| ls -lh "$ORT_PATH/libonnxruntime.a" |
This makes build failures explicit and immediate rather than downstream.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 72:76
Comment:
The "Verify ONNX Runtime files" step runs unconditionally, but if the download step failed, this verification will also fail silently (due to the `|| echo` fallback). The build will continue even though critical files are missing, leading to build failure downstream with confusing error messages.
The verification step should explicitly check if the required directory exists and fail the workflow if it doesn't:
```suggestion
- name: Verify ONNX Runtime files
run: |
ORT_PATH="${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"
if [ ! -f "$ORT_PATH/libonnxruntime.a" ]; then
echo "ERROR: ONNX Runtime library not found at $ORT_PATH/libonnxruntime.a"
exit 1
fi
echo "ONNX Runtime files verified successfully"
ls -lh "$ORT_PATH/libonnxruntime.a"
```
This makes build failures explicit and immediate rather than downstream.
How can I resolve this? If you propose a fix, please make it concise.| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done |
There was a problem hiding this comment.
The curl commands don't check HTTP status codes or validate download success. If HuggingFace returns a 404, authentication error (403), or server error (5xx), the download will fail silently, creating empty or corrupt files. The script will then report success when actually it failed to download the required files.
Add error checking after each download:
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading headers..." | |
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | |
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | |
| done | |
| echo "Downloading Info.plist..." | |
| if ! curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist"; then | |
| echo "ERROR: Failed to download Info.plist" | |
| rm -rf "$ORT_DIR" | |
| exit 1 | |
| fi |
The --fail flag makes curl exit with an error on HTTP failures (4xx/5xx status codes). Apply this to all curl downloads.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 52:59
Comment:
The curl commands don't check HTTP status codes or validate download success. If HuggingFace returns a 404, authentication error (403), or server error (5xx), the download will fail silently, creating empty or corrupt files. The script will then report success when actually it failed to download the required files.
Add error checking after each download:
```suggestion
echo "Downloading Info.plist..."
if ! curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist"; then
echo "ERROR: Failed to download Info.plist"
rm -rf "$ORT_DIR"
exit 1
fi
```
The `--fail` flag makes curl exit with an error on HTTP failures (4xx/5xx status codes). Apply this to all curl downloads.
How can I resolve this? If you propose a fix, please make it concise.The xcodebuild process runs cargo in a subprocess that doesn't inherit GitHub Actions environment variables. This config file uses Cargo's [env] section to set ORT_LIB_LOCATION, which will be read by ort-sys when cargo builds the iOS target. Also adds target-specific rustflags to ensure the linker can find the ONNX Runtime static library for each iOS target. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The previous approach broke both desktop and iOS builds: - [env] section applied ORT_LIB_LOCATION to ALL targets, breaking desktop - rustflags with -l applied to ALL crate compilations, including libc This fix uses Cargo's [target.<triple>.<links>] feature to override ort-sys's build script output ONLY for iOS targets. The 'onnxruntime' key matches ort-sys's 'links = "onnxruntime"' declaration. This is the correct way to provide library paths for specific targets without affecting other targets or crate compilations. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
Adds iOS support for on-device TTS using ONNX Runtime 1.20.1 and the Supertonic model. The implementation mirrors the existing desktop TTS, downloading pre-built xcframework binaries from HuggingFace and storing TTS models in ~/Documents/tts_models.
Key Changes:
- Added iOS-specific ONNX Runtime dependencies to
Cargo.tomlwithortconfigured for static linking - Created build infrastructure (
build.rs,.cargo/config.toml) to link xcframework libraries for both device and simulator targets - Extended TTS module availability from desktop-only to desktop + iOS
- Added GitHub Actions steps to cache and download ONNX Runtime binaries
- Frontend platform detection updated to enable TTS on iOS
Issues Found:
- Configuration inconsistency:
ORT_LIB_LOCATIONis set in three places (build.rs,.cargo/config.toml, GitHub Actions) with conflicting values (base directory vs subdirectory vs absolute path) - Performance gap: iOS build missing
rayonfeature forndarray, which will result in 5-10x slower tensor operations compared to desktop - Security concern: Download script doesn't verify integrity of ~200MB binary libraries from HuggingFace
- Maintainability: Hardcoded device-only paths in workflows and config will cause issues if simulator builds are needed
The core implementation is solid with proper error handling in Rust and correct platform detection in TypeScript. However, the build configuration has redundancy and inconsistencies that should be cleaned up to avoid future build failures.
Confidence Score: 3/5
- This PR has multiple configuration inconsistencies that need attention before merge
- Core logic is sound with proper error handling and platform detection. However, critical build configuration issues exist: ORT_LIB_LOCATION is inconsistently defined across three locations causing potential build failures, missing performance optimization (rayon), and lack of binary integrity verification. These are style/best-practice issues rather than breaking bugs, but they impact reliability and should be addressed.
- Pay close attention to
build.rs,.cargo/config.toml, andsetup-ios-onnxruntime.sh- configuration conflicts and missing security checks
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/Cargo.toml | 4/5 | Added iOS TTS dependencies mirroring desktop config. Missing rayon feature for ndarray which will impact performance. |
| frontend/src-tauri/build.rs | 3/5 | iOS-specific ONNX Runtime linking configuration added. ORT_LIB_LOCATION setting conflicts with .cargo/config.toml. |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 3/5 | Downloads ONNX Runtime xcframework from HuggingFace. Missing integrity verification for downloaded binaries (~200MB). |
| .github/workflows/mobile-build.yml | 4/5 | Added ONNX Runtime caching and download steps. ORT_LIB_LOCATION hardcoded to device path, may conflict with build.rs. |
| frontend/src-tauri/.cargo/config.toml | 3/5 | iOS linking configuration for ONNX Runtime. ORT_LIB_LOCATION hardcoded to device path but applies to all targets. |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Script as setup-ios-onnxruntime.sh
participant HF as HuggingFace
participant Cargo as Cargo Build
participant ORT as ONNX Runtime
participant App as iOS App
Note over GHA: iOS Build Triggered
GHA->>GHA: Check cache for onnxruntime-ios
alt Cache Miss
GHA->>Script: Execute setup script
Script->>HF: Download xcframework files
HF-->>Script: Info.plist, headers, .a libraries
Script->>Script: Save to onnxruntime-ios/
else Cache Hit
GHA->>GHA: Restore cached files
end
GHA->>GHA: Set ORT_LIB_LOCATION env var
GHA->>Cargo: Start build (bun tauri ios build)
Note over Cargo: Build Process
Cargo->>Cargo: Read .cargo/config.toml
Cargo->>Cargo: Execute build.rs
Note over Cargo: Sets ORT_LIB_LOCATION (conflicts with config.toml)
Cargo->>Cargo: Detect target (device/simulator)
Cargo->>Cargo: Set rustflags for linking
Cargo->>ORT: Link static libraries
ORT->>ORT: Load libonnxruntime.a
Cargo->>Cargo: Compile TTS module
Cargo->>Cargo: Build iOS binary
Cargo-->>App: Generate .ipa file
Note over App: Runtime
App->>App: User requests TTS
App->>App: Download TTS models (~264MB)
App->>ORT: Load models & synthesize
ORT-->>App: Return audio data
| # We disable download-binaries and copy-dylibs since we link our own xcframework | ||
| # Need "std" for Error trait impl and file operations, "ndarray" for tensor creation | ||
| ort = { version = "2.0.0-rc.10", default-features = false, features = ["std", "ndarray"] } | ||
| ndarray = { version = "0.16" } |
There was a problem hiding this comment.
iOS build missing rayon feature for ndarray - desktop has it on line 45. Without parallel processing, TTS inference will be significantly slower on iOS (5-10x slower for tensor operations). Consider adding features = ["rayon"] unless there's a specific reason to exclude it.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/Cargo.toml
Line: 62:62
Comment:
iOS build missing `rayon` feature for `ndarray` - desktop has it on line 45. Without parallel processing, TTS inference will be significantly slower on iOS (5-10x slower for tensor operations). Consider adding `features = ["rayon"]` unless there's a specific reason to exclude it.
How can I resolve this? If you propose a fix, please make it concise.| println!("cargo:rustc-link-lib=framework=Accelerate"); | ||
|
|
||
| // Set ORT_LIB_LOCATION for the ort crate | ||
| println!("cargo:rustc-env=ORT_LIB_LOCATION={}", ort_dir); |
There was a problem hiding this comment.
Inconsistent ORT_LIB_LOCATION configuration. This sets it to {manifest_dir}/onnxruntime-ios (base directory), but .cargo/config.toml line 11 sets it to onnxruntime-ios/onnxruntime.xcframework/ios-arm64 (subdirectory), and GitHub Actions sets it to the full absolute path with subdirectory. The .cargo/config.toml value will override this, making this line ineffective. Either remove this line or ensure all three locations use consistent paths.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 26:26
Comment:
Inconsistent `ORT_LIB_LOCATION` configuration. This sets it to `{manifest_dir}/onnxruntime-ios` (base directory), but `.cargo/config.toml` line 11 sets it to `onnxruntime-ios/onnxruntime.xcframework/ios-arm64` (subdirectory), and GitHub Actions sets it to the full absolute path with subdirectory. The `.cargo/config.toml` value will override this, making this line ineffective. Either remove this line or ensure all three locations use consistent paths.
How can I resolve this? If you propose a fix, please make it concise.| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
Missing checksum/signature verification for downloaded files. The script downloads ~200MB of binary libraries from HuggingFace but doesn't verify their integrity. If the remote files are compromised or corrupted, this could fail silently or worse, include malicious code. Consider adding SHA256 verification for the downloaded .a files, similar to how tts.rs verifies model file integrity (lines 876-883).
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 62:67
Comment:
Missing checksum/signature verification for downloaded files. The script downloads ~200MB of binary libraries from HuggingFace but doesn't verify their integrity. If the remote files are compromised or corrupted, this could fail silently or worse, include malicious code. Consider adding SHA256 verification for the downloaded `.a` files, similar to how `tts.rs` verifies model file integrity (lines 876-883).
How can I resolve this? If you propose a fix, please make it concise.| VITE_MAPLE_BILLING_API_URL: https://billing.opensecret.cloud | ||
| VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6 | ||
| # ONNX Runtime location for ort-sys crate | ||
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 |
There was a problem hiding this comment.
ORT_LIB_LOCATION points to device-specific path (ios-arm64) but the workflow only builds for device, not simulator. If simulator builds are needed in the future, this will cause linker errors. The path should be consistent with what build.rs selects based on target (device vs simulator). Consider whether this env var is even needed since build.rs and .cargo/config.toml already handle this.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 115:115
Comment:
`ORT_LIB_LOCATION` points to device-specific path (`ios-arm64`) but the workflow only builds for device, not simulator. If simulator builds are needed in the future, this will cause linker errors. The path should be consistent with what `build.rs` selects based on target (device vs simulator). Consider whether this env var is even needed since `build.rs` and `.cargo/config.toml` already handle this.
How can I resolve this? If you propose a fix, please make it concise.| VITE_MAPLE_BILLING_API_URL: https://billing.opensecret.cloud | ||
| VITE_CLIENT_ID: ba5a14b5-d915-47b1-b7b1-afda52bc5fc6 | ||
| # ONNX Runtime location for ort-sys crate | ||
| ORT_LIB_LOCATION: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64 |
There was a problem hiding this comment.
Same ORT_LIB_LOCATION issue as in mobile-build.yml - hardcoded to device path but doesn't match the dynamic selection in build.rs. This creates maintenance issues and potential build failures if simulator builds are ever needed.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 173:173
Comment:
Same `ORT_LIB_LOCATION` issue as in `mobile-build.yml` - hardcoded to device path but doesn't match the dynamic selection in `build.rs`. This creates maintenance issues and potential build failures if simulator builds are ever needed.
How can I resolve this? If you propose a fix, please make it concise.| # The `onnxruntime` key matches ort-sys's `links = "onnxruntime"` declaration. | ||
|
|
||
| # iOS arm64 device target - override ort-sys build script | ||
| [target.aarch64-apple-ios.onnxruntime] |
There was a problem hiding this comment.
Hardcoded to ios-arm64 device path. This value is used for ALL targets (device + simulators) per line 9 comment, but device and simulator need different paths. The target-specific rustflags on lines 14-32 correctly point to different directories, but this env var doesn't. If ort-sys uses this env var, simulator builds may fail. Verify whether this env var is needed at all since build.rs already sets it dynamically.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/.cargo/config.toml
Line: 11:11
Comment:
Hardcoded to `ios-arm64` device path. This value is used for ALL targets (device + simulators) per line 9 comment, but device and simulator need different paths. The target-specific `rustflags` on lines 14-32 correctly point to different directories, but this env var doesn't. If `ort-sys` uses this env var, simulator builds may fail. Verify whether this env var is needed at all since `build.rs` already sets it dynamically.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
frontend/src-tauri/.cargo/config.toml (1)
14-32: Verify you’re not double-linkinglibonnxruntime.a(ort-sys vs rustflags).You’re passing
-l static=onnxruntimeviarustflagsfor all iOS targets. Ifort-sysalready emitscargo:rustc-link-lib=static=onnxruntime, this can become redundant at best (bigger/messier link lines) or cause duplicate/ordering issues depending on how the final link is composed.If
ort-sysalready links the library, consider keeping only the per-target-L native=...here and lettingort-sysown the-ldirective.Proposed change (only if ort-sys already emits the `-l`)
[target.aarch64-apple-ios] rustflags = [ "-L", "native=onnxruntime-ios/onnxruntime.xcframework/ios-arm64", - "-l", "static=onnxruntime", ] [target.aarch64-apple-ios-sim] rustflags = [ "-L", "native=onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator", - "-l", "static=onnxruntime", ] [target.x86_64-apple-ios] rustflags = [ "-L", "native=onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator", - "-l", "static=onnxruntime", ]
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
frontend/src-tauri/.cargo/config.toml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Follow standard Rust conventions and rustfmt defaults for code formatting
Applied to files:
frontend/src-tauri/.cargo/config.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build-linux
- GitHub Check: build-android
- GitHub Check: build-macos (universal-apple-darwin)
🔇 Additional comments (1)
frontend/src-tauri/.cargo/config.toml (1)
5-12: This review comment is based on an incorrect or outdated view of the file. The actual.cargo/config.tomldoes not contain a global[env]section—it correctly uses target-specific Cargo config overrides instead.Actual structure (lines 1–23):
[target.aarch64-apple-ios.onnxruntime]→ios-arm64(device)[target.aarch64-apple-ios-sim.onnxruntime]→ios-arm64_x86_64-simulator(simulator)[target.x86_64-apple-ios.onnxruntime]→ios-arm64_x86_64-simulator(simulator x86_64)This target-specific approach avoids the global environment leakage concern. The
build.rsalso correctly selects per-target paths (lines 12–14 show conditional logic for simulator vs. device). Workflows setORT_LIB_LOCATIONin the CI environment context only, which is appropriate.The implementation is correct and does not have the issue described in the review comment.
Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS support for on-device Text-to-Speech (TTS) using the Supertonic model via ONNX Runtime. The implementation mirrors the existing desktop TTS functionality with iOS-specific adaptations.
Key Changes
Infrastructure:
- Downloads pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace during build
- Adds GitHub Actions caching to speed up builds (xcframework is ~100MB)
- Uses Cargo build script override (
.cargo/config.toml) to link ONNX Runtime statically for iOS targets
iOS-Specific Adaptations:
- TTS models (~264MB) stored in
~/Documents/tts_modelson iOS (vs app data dir on desktop) - Uses iOS Documents directory for persistence, which has iCloud sync implications
- Omits
rayonparallel processing feature fromndarraydependency on iOS
Code Architecture:
- Enables
ttsmodule for iOS using#[cfg(any(desktop, target_os = "ios"))] - Adds iOS-specific configuration block in
lib.rswith TTS command handlers - Frontend detects iOS via platform utils and enables TTS UI accordingly
Issues Found
Critical (Logic):
- ✅ Shell script curl commands don't use
--failflag, could download error pages instead of binaries - ✅ Workflow verification steps use
|| echowhich prevents build failures on missing libraries
Important (Style):
3. ✅ iOS models stored in ~/Documents will sync to iCloud (264MB), better to use Application Support
4. ✅ ONNX Runtime downloads from HuggingFace main branch (not pinned to commit hash like TTS models)
Architecture Integration
The implementation integrates cleanly with existing TTS infrastructure. The Rust backend handles all inference work, while the frontend simply invokes Tauri commands and plays returned audio. Models are downloaded on-demand, same as desktop. Memory usage (~500MB) is acceptable for modern iOS devices (iPhone 12+).
The conditional compilation strategy properly separates iOS, Android, and desktop paths, though the control flow in lib.rs is somewhat complex with multiple cfg blocks.
Confidence Score: 4/5
- This PR is generally safe to merge with some minor improvements recommended
- Score reflects solid implementation with well-structured code, but has a few issues that should be addressed: (1) download script lacks robust error handling for HTTP failures, (2) workflow verification steps don't fail builds properly, (3) iOS storage location may cause iCloud sync overhead, and (4) ONNX Runtime downloads from unpinned branch. The core TTS logic is proven (already works on desktop), and the iOS adaptations are straightforward. The issues found are operational/configuration concerns rather than logic bugs. All critical paths have proper error handling with Result types.
- Pay close attention to setup-ios-onnxruntime.sh (download reliability), mobile-build.yml and testflight-on-comment.yml (verification steps), and tts.rs (iOS storage location)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 3/5 | Download script for ONNX Runtime lacks explicit HTTP status checks and final verification |
| .github/workflows/mobile-build.yml | 4/5 | iOS build workflow with ONNX Runtime caching and verification, but verification doesn't fail on error |
| .github/workflows/testflight-on-comment.yml | 4/5 | TestFlight deployment workflow with same ONNX Runtime setup as mobile-build, verification doesn't fail on error |
| frontend/src-tauri/Cargo.toml | 4/5 | Adds iOS-specific TTS dependencies, omits rayon feature for ndarray (will reduce parallel processing performance) |
| frontend/src-tauri/build.rs | 4/5 | Adds iOS-specific ONNX Runtime linking configuration, correctly handles simulator vs device targets |
| frontend/src-tauri/src/lib.rs | 4/5 | Enables TTS module and commands for iOS with proper conditional compilation, complex but correct control flow |
| frontend/src-tauri/src/tts.rs | 3/5 | Adds iOS-specific path handling using ~/Documents which may cause iCloud sync and storage issues |
Sequence Diagram
sequenceDiagram
participant User
participant Frontend as Frontend (React)
participant Tauri as Tauri Backend (Rust)
participant FS as File System
participant HF as HuggingFace
participant ONNX as ONNX Runtime
Note over User,ONNX: iOS TTS Initialization Flow
User->>Frontend: Open app on iOS
Frontend->>Tauri: tts_get_status()
Tauri->>FS: Check ~/Documents/tts_models/
FS-->>Tauri: Models not found
Tauri-->>Frontend: models_downloaded: false
Note over User,ONNX: Model Download Flow
User->>Frontend: Click "Download TTS Models"
Frontend->>Tauri: tts_download_models()
loop For each model file (10 files, 264MB total)
Tauri->>HF: Download model file with SHA256
HF-->>Tauri: Model file chunk
Tauri->>Tauri: Verify checksum
Tauri->>FS: Save to ~/Documents/tts_models/
Tauri->>Frontend: Emit download progress event
Frontend->>User: Update progress bar
end
Tauri-->>Frontend: Download complete
Frontend->>Tauri: tts_load_models()
Tauri->>FS: Read model files
Tauri->>ONNX: Load ONNX sessions (4 models)
ONNX-->>Tauri: Sessions ready (~500MB RAM)
Tauri-->>Frontend: Models loaded
Note over User,ONNX: TTS Synthesis Flow
User->>Frontend: Click TTS button on message
Frontend->>Tauri: tts_synthesize(text)
Tauri->>Tauri: Preprocess text (remove markdown, etc.)
Tauri->>Tauri: Chunk text into 300-char segments
loop For each text chunk
Tauri->>ONNX: Run text_encoder
Tauri->>ONNX: Run duration_predictor
Tauri->>ONNX: Run vector_estimator (10 steps)
Tauri->>ONNX: Run vocoder
ONNX-->>Tauri: Audio samples (float32)
end
Tauri->>Tauri: Concatenate audio chunks
Tauri->>Tauri: Encode to WAV + base64
Tauri-->>Frontend: audio_base64, sample_rate
Frontend->>Frontend: Decode base64 to Blob
Frontend->>Frontend: Play via Web Audio API
Frontend-->>User: Play audio
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | ||
|
|
||
| echo "Downloading headers..." | ||
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | ||
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | ||
| done | ||
|
|
||
| echo "Downloading iOS arm64 static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | ||
|
|
||
| echo "Downloading iOS simulator static library (this may take a while)..." | ||
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
The curl commands don't use the --fail flag, which means they will succeed even if the server returns a 404 or other error status. This could result in downloading HTML error pages instead of the actual files.
Consider adding --fail to all curl commands to ensure they fail on HTTP errors:
| curl -L -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading headers..." | |
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | |
| curl -L -o "$XCFRAMEWORK_DIR/Headers/$header" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | |
| done | |
| echo "Downloading iOS arm64 static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| echo "Downloading iOS simulator static library (this may take a while)..." | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" | |
| echo "Downloading Info.plist..." | |
| curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist" | |
| echo "Downloading headers..." | |
| for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do | |
| curl -L --fail -o "$XCFRAMEWORK_DIR/Headers/$header" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header" | |
| done | |
| echo "Downloading iOS arm64 static library (this may take a while)..." | |
| curl -L --fail -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| echo "Downloading iOS simulator static library (this may take a while)..." | |
| curl -L --fail -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 52:67
Comment:
The curl commands don't use the `--fail` flag, which means they will succeed even if the server returns a 404 or other error status. This could result in downloading HTML error pages instead of the actual files.
Consider adding `--fail` to all curl commands to ensure they fail on HTTP errors:
```suggestion
echo "Downloading Info.plist..."
curl -L --fail -o "$XCFRAMEWORK_DIR/Info.plist" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Info.plist"
echo "Downloading headers..."
for header in cpu_provider_factory.h onnxruntime_c_api.h onnxruntime_cxx_api.h onnxruntime_cxx_inline.h; do
curl -L --fail -o "$XCFRAMEWORK_DIR/Headers/$header" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/Headers/$header"
done
echo "Downloading iOS arm64 static library (this may take a while)..."
curl -L --fail -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a"
echo "Downloading iOS simulator static library (this may take a while)..."
curl -L --fail -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a"
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Verify ONNX Runtime files | ||
| run: | | ||
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | ||
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | ||
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" |
There was a problem hiding this comment.
The verification step uses || echo which means it will never fail the build even if the ONNX Runtime library is missing or invalid. This could lead to cryptic build failures in the next step.
The verification should fail the build if the file is missing:
| - name: Verify ONNX Runtime files | |
| run: | | |
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" | |
| - name: Verify ONNX Runtime files | |
| run: | | |
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | |
| # Verify it's actually a static library | |
| if ! file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | grep -q "ar archive"; then | |
| echo "ERROR: libonnxruntime.a is not a valid static library" | |
| exit 1 | |
| fi |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 72:76
Comment:
The verification step uses `|| echo` which means it will never fail the build even if the ONNX Runtime library is missing or invalid. This could lead to cryptic build failures in the next step.
The verification should fail the build if the file is missing:
```suggestion
- name: Verify ONNX Runtime files
run: |
echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"
ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/
file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a
# Verify it's actually a static library
if ! file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | grep -q "ar archive"; then
echo "ERROR: libonnxruntime.a is not a valid static library"
exit 1
fi
```
How can I resolve this? If you propose a fix, please make it concise.| - name: Verify ONNX Runtime files | ||
| run: | | ||
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | ||
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | ||
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" |
There was a problem hiding this comment.
Same issue as in mobile-build.yml - the verification step uses || echo which means it will never fail the build even if the ONNX Runtime library is missing or invalid.
| - name: Verify ONNX Runtime files | |
| run: | | |
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a || echo "File not found or not a valid archive" | |
| - name: Verify ONNX Runtime files | |
| run: | | |
| echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64" | |
| ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/ | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | |
| # Verify it's actually a static library | |
| if ! file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | grep -q "ar archive"; then | |
| echo "ERROR: libonnxruntime.a is not a valid static library" | |
| exit 1 | |
| fi |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 130:134
Comment:
Same issue as in mobile-build.yml - the verification step uses `|| echo` which means it will never fail the build even if the ONNX Runtime library is missing or invalid.
```suggestion
- name: Verify ONNX Runtime files
run: |
echo "ORT_LIB_LOCATION will be: ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"
ls -la ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/
file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a
# Verify it's actually a static library
if ! file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a | grep -q "ar archive"; then
echo "ERROR: libonnxruntime.a is not a valid static library"
exit 1
fi
```
How can I resolve this? If you propose a fix, please make it concise.| fn get_tts_models_dir() -> Result<PathBuf> { | ||
| let data_dir = dirs::data_local_dir() | ||
| .context("Failed to get local data directory")? | ||
| .join("cloud.opensecret.maple") | ||
| .join("tts_models"); | ||
| Ok(data_dir) | ||
| // On iOS, we need to use a different approach since dirs::data_local_dir() may not work | ||
| #[cfg(target_os = "ios")] | ||
| { | ||
| // On iOS, use the app's Documents directory which is accessible and persists | ||
| // NSHomeDirectory() + /Documents/tts_models | ||
| let home = std::env::var("HOME").context("Failed to get HOME directory on iOS")?; | ||
| let data_dir = PathBuf::from(home).join("Documents").join("tts_models"); | ||
| return Ok(data_dir); | ||
| } |
There was a problem hiding this comment.
On iOS, storing TTS models (~264MB) in ~/Documents/tts_models has several implications:
- iCloud sync: The Documents directory is backed up to iCloud by default, which will use significant iCloud storage and bandwidth
- User visibility: Users can see this folder in the Files app, which may be confusing
- Storage: Users may delete it thinking it's unnecessary
iOS best practice is to use the Application Support directory for app-specific data that users don't need to access. Consider using a directory like:
~/Library/Application Support/cloud.opensecret.maple/tts_models(not backed up to iCloud)- Or mark the Documents subdirectory as excluded from backup using file attributes
This is particularly important given the 264MB size of the models.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/tts.rs
Line: 614:623
Comment:
On iOS, storing TTS models (~264MB) in `~/Documents/tts_models` has several implications:
1. **iCloud sync**: The Documents directory is backed up to iCloud by default, which will use significant iCloud storage and bandwidth
2. **User visibility**: Users can see this folder in the Files app, which may be confusing
3. **Storage**: Users may delete it thinking it's unnecessary
iOS best practice is to use the Application Support directory for app-specific data that users don't need to access. Consider using a directory like:
- `~/Library/Application Support/cloud.opensecret.maple/tts_models` (not backed up to iCloud)
- Or mark the Documents subdirectory as excluded from backup using file attributes
This is particularly important given the 264MB size of the models.
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| # Download pre-built xcframework from HuggingFace | ||
| # Repository: https://huggingface.co/csukuangfj/ios-onnxruntime | ||
| HF_BASE_URL="https://huggingface.co/csukuangfj/ios-onnxruntime/resolve/main" |
There was a problem hiding this comment.
The script downloads from the main branch of the HuggingFace repository, which means the files could change over time without notice. This differs from the TTS model downloads in tts.rs which pin to a specific commit hash (b6856d033f622c63ea29441795be266a1133e227) for security and reproducibility.
Consider pinning to a specific commit hash instead of using main:
| HF_BASE_URL="https://huggingface.co/csukuangfj/ios-onnxruntime/resolve/main" | |
| HF_BASE_URL="https://huggingface.co/csukuangfj/ios-onnxruntime/resolve/<commit-hash>" |
This ensures builds are reproducible and protects against potential supply chain attacks if the repository is compromised.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 29:29
Comment:
The script downloads from the `main` branch of the HuggingFace repository, which means the files could change over time without notice. This differs from the TTS model downloads in `tts.rs` which pin to a specific commit hash (`b6856d033f622c63ea29441795be266a1133e227`) for security and reproducibility.
Consider pinning to a specific commit hash instead of using `main`:
```suggestion
HF_BASE_URL="https://huggingface.co/csukuangfj/ios-onnxruntime/resolve/<commit-hash>"
```
This ensures builds are reproducible and protects against potential supply chain attacks if the repository is compromised.
How can I resolve this? If you propose a fix, please make it concise.The static .cargo/config.toml with relative paths wasn't working because: 1. xcodebuild may run cargo from different working directories 2. Relative paths in config files are relative to the config file location, which may not match the actual library location in CI This fix generates the config file dynamically in GitHub Actions with absolute paths to the ONNX Runtime library location, ensuring the build script override works regardless of the working directory. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @.github/workflows/mobile-build.yml:
- Around line 72-77: The "Verify ONNX Runtime files" workflow step currently
swallows failures by using `file ... || echo ...`; change it to fail-fast so
missing or invalid ORT artifacts stop the run: replace the `file ${{
github.workspace
}}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/libonnxruntime.a
|| echo "File not found or not a valid archive"` pattern with a strict check
that exits non-zero on failure (e.g., run `file` and if it indicates an error or
the archive is absent, call `exit 1` or use a conditional that fails), and
ensure the `ls`/`file` invocations in the "Verify ONNX Runtime files" step
reference the same path shown in the diff so the workflow fails when
libonnxruntime.a is missing or corrupt.
🧹 Nitpick comments (1)
.github/workflows/mobile-build.yml (1)
56-64: Cache key/restore-keys are too static; risk of stale/poisoned ORT artifacts.
Right now the key won’t change if the download script/URL changes, andrestore-keysduplicates the full key (no fallback behavior).Proposed tweak
- name: Cache ONNX Runtime iOS xcframework uses: actions/cache@v4 id: cache-onnxruntime with: path: frontend/src-tauri/onnxruntime-ios - key: onnxruntime-ios-1.20.1-v2 + key: onnxruntime-ios-1.20.1-${{ hashFiles('frontend/src-tauri/scripts/setup-ios-onnxruntime.sh') }} restore-keys: | - onnxruntime-ios-1.20.1-v2 + onnxruntime-ios-1.20.1-
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.yml
🚧 Files skipped from review as they are similar to previous changes (1)
- .github/workflows/testflight-on-comment.yml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/mobile-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
- GitHub Check: build-android
- GitHub Check: build-ios
- GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
.github/workflows/mobile-build.yml (2)
140-141: [Rewritten review comment]
[Exactly ONE classification tag]
65-71: Supply-chain hardening: downloaded prebuilt xcframework needs integrity verification.
This pulls a large prebuilt binary from an external source but doesn't pin/verify a checksum/signature in CI.Actionable ask: have
scripts/setup-ios-onnxruntime.sh(or this workflow) verify a known SHA-256 (and fail if mismatched).
| - name: Configure Cargo for iOS ONNX Runtime | ||
| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our pre-built library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
| EOF | ||
|
|
||
| echo "Generated cargo config:" | ||
| cat "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" | ||
|
|
There was a problem hiding this comment.
Don’t blindly overwrite .cargo/config.toml; also ensure simulator targets are actually installed if needed.
This unconditionally writes frontend/src-tauri/.cargo/config.toml, which can clobber repo config if it exists (now or later). Also, you configure aarch64-apple-ios-sim / x86_64-apple-ios, but only install aarch64-apple-ios (Line 23).
Suggested adjustments:
- Write to a separate file (or back up/restore an existing config).
- If the build can hit simulator targets, add Rust targets:
aarch64-apple-ios-sim,x86_64-apple-ios(or explicitly ensure the workflow only builds device).
Replace pre-built HuggingFace library with building ONNX Runtime from source. The pre-built library lacked statically-linked Abseil dependencies required for Rust static linking. Changes: - Add build-ios-onnxruntime.sh script that builds ONNX Runtime 1.20.1 from Microsoft's official repo for iOS device and simulator - Update GitHub Actions workflows to use build-from-source approach - Cache both build directory and output xcframework for CI efficiency - Add 90-minute timeout for initial builds (subsequent builds are cached) - Update .gitignore for build artifacts The built-from-source library includes all dependencies (Abseil, etc.) statically linked, resolving the undefined symbols errors. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The google_nsync dependency requires an older CMake minimum version that's no longer supported by newer CMake versions. Adding CMAKE_POLICY_VERSION_MINIMUM=3.5 works around this compatibility issue. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech (TTS) support for iOS using ONNX Runtime, enabling the Supertonic TTS model to run on-device. The implementation builds ONNX Runtime 1.20.1 from source during CI builds (despite PR description mentioning pre-built binaries), caches the compiled xcframework, and integrates it with the iOS Tauri app.
Key Changes:
- Build Infrastructure: Adds GitHub Actions steps to build ONNX Runtime from source for iOS device and simulator architectures, with aggressive caching to speed up subsequent builds
- Rust Integration: Enables TTS module for iOS (previously desktop-only), adds iOS-specific ONNX Runtime linking in build.rs, and includes iOS TTS commands in the invoke handler
- iOS Storage: Uses
~/Documents/tts_modelsfor model storage on iOS instead of the standard app data directory - Frontend: Updates TTS context to recognize iOS as a supported platform alongside desktop
Implementation Approach:
The implementation mirrors the desktop TTS functionality - models (~264MB) are downloaded on-demand from HuggingFace, ONNX Runtime runs inference on-device, and audio is synthesized locally. Memory usage is approximately 500MB RAM.
Technical Notes:
- The PR includes an unused
setup-ios-onnxruntime.shscript for downloading pre-built binaries, but workflows actually usebuild-ios-onnxruntime.shto compile from source - Build configuration uses multiple mechanisms (build.rs, .cargo/config.toml generation, environment variables) which may have some redundancy
- The Cargo config generation uses non-standard table syntax that may not be recognized by Cargo
Confidence Score: 4/5
- Safe to merge with minor configuration issues that may need follow-up testing
- The core implementation is sound - TTS module integration, iOS-specific paths, and dependency configuration are correct. However, there are configuration inconsistencies: (1) the Cargo config generation uses non-standard syntax that may be ignored, (2) ORT_LIB_LOCATION paths differ between build.rs and workflow, and (3) an unused setup script suggests incomplete cleanup. These are style/configuration issues that won't break the build since build.rs provides fallback configuration, but they should be verified in testing.
- The GitHub Actions workflow files (.github/workflows/mobile-build.yml and testflight-on-comment.yml) should be tested to verify the Cargo config syntax works as intended, and build.rs should be aligned with the workflow's ORT_LIB_LOCATION path for consistency.
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 4/5 | Adds ONNX Runtime iOS build steps with caching, library verification, and Cargo configuration generation |
| .github/workflows/testflight-on-comment.yml | 4/5 | Duplicates ONNX Runtime build configuration from mobile-build.yml for TestFlight deployments |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies with custom ort features (std, ndarray, no download-binaries) |
| frontend/src-tauri/build.rs | 3/5 | Adds iOS-specific ONNX Runtime linking configuration, but has path inconsistency with workflow env var |
| frontend/src-tauri/src/lib.rs | 4/5 | Enables TTS module for iOS, adds TTS commands to iOS invoke handler, manages TTS state |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling for TTS models using HOME/Documents/tts_models directory |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Updates TTS availability check to include iOS alongside desktop platforms |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 4/5 | New script to build ONNX Runtime from source for iOS device and simulator architectures |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant Cargo as Cargo Build System
participant BuildRS as build.rs
participant App as Tauri iOS App
participant TTS as TTS Module
participant ONNX as ONNX Runtime
Note over GHA,Build: Build Phase
GHA->>GHA: Cache check for ONNX Runtime
alt Cache miss
GHA->>Build: Execute build-ios-onnxruntime.sh
Build->>Build: Clone ONNX Runtime v1.20.1
Build->>Build: Build for iOS device (arm64)
Build->>Build: Build for iOS simulator (arm64 + x86_64)
Build->>Build: Create xcframework structure
Build->>GHA: Return built libraries
end
GHA->>GHA: Verify ONNX Runtime libraries
GHA->>GHA: Generate .cargo/config.toml with paths
GHA->>GHA: Set ORT_LIB_LOCATION env var
Note over GHA,Cargo: Compilation Phase
GHA->>Cargo: Start iOS build
Cargo->>BuildRS: Execute build.rs
BuildRS->>BuildRS: Detect iOS target
BuildRS->>BuildRS: Set library search paths
BuildRS->>BuildRS: Set ORT_LIB_LOCATION (overridden by env)
BuildRS->>Cargo: Return link flags
Cargo->>Cargo: Compile Rust code with ONNX Runtime
Cargo->>GHA: iOS app binary
Note over App,ONNX: Runtime Phase
App->>App: Launch on iOS device
App->>TTS: User requests TTS
TTS->>TTS: Check models in ~/Documents/tts_models
alt Models not present
TTS->>TTS: Download models from HuggingFace
end
TTS->>ONNX: Load ONNX models
ONNX->>ONNX: Initialize inference sessions
TTS->>TTS: Process text input
TTS->>ONNX: Run inference
ONNX->>TTS: Return audio samples
TTS->>App: Play synthesized audio
| println!("cargo:rustc-link-lib=framework=Accelerate"); | ||
|
|
||
| // Set ORT_LIB_LOCATION for the ort crate | ||
| println!("cargo:rustc-env=ORT_LIB_LOCATION={}", ort_dir); |
There was a problem hiding this comment.
[P2] The ORT_LIB_LOCATION set here points to onnxruntime-ios directory, but the GitHub Actions workflow sets it to onnxruntime-ios/onnxruntime.xcframework/ios-arm64. The workflow environment variable will override this build.rs setting, which creates inconsistency between local and CI builds. Consider either removing this line or aligning the paths.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 26:26
Comment:
[P2] The `ORT_LIB_LOCATION` set here points to `onnxruntime-ios` directory, but the GitHub Actions workflow sets it to `onnxruntime-ios/onnxruntime.xcframework/ios-arm64`. The workflow environment variable will override this build.rs setting, which creates inconsistency between local and CI builds. Consider either removing this line or aligning the paths.
How can I resolve this? If you propose a fix, please make it concise.| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our pre-built library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
[P2] This dynamically generated .cargo/config.toml uses [target.*.onnxruntime] table names, but standard Cargo config uses section names without dots after the target triple. The correct format should be [target.aarch64-apple-ios] with rustc-link-search directly under it, not nested under onnxruntime. This non-standard syntax may be ignored by Cargo, making the configuration ineffective.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 88:107
Comment:
[P2] This dynamically generated `.cargo/config.toml` uses `[target.*.onnxruntime]` table names, but standard Cargo config uses section names without dots after the target triple. The correct format should be `[target.aarch64-apple-ios]` with `rustc-link-search` directly under it, not nested under `onnxruntime`. This non-standard syntax may be ignored by Cargo, making the configuration ineffective.
How can I resolve this? If you propose a fix, please make it concise.| - name: Configure Cargo for iOS ONNX Runtime | ||
| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our pre-built library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] |
There was a problem hiding this comment.
[P2] Same Cargo config syntax issue as mobile-build.yml. The [target.*.onnxruntime] table syntax is non-standard and likely ignored by Cargo. Should use [target.aarch64-apple-ios] format instead.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 145:164
Comment:
[P2] Same Cargo config syntax issue as mobile-build.yml. The `[target.*.onnxruntime]` table syntax is non-standard and likely ignored by Cargo. Should use `[target.aarch64-apple-ios]` format instead.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS TTS support using ONNX Runtime, enabling the Supertonic TTS model to run on-device on iPhones and iPads. The implementation mirrors the existing desktop TTS functionality and downloads a pre-built ONNX Runtime 1.20.1 xcframework from HuggingFace.
Key Changes
Build Infrastructure:
- New
setup-ios-onnxruntime.shscript downloads pre-built ONNX Runtime xcframework from HuggingFace - GitHub Actions workflows updated with caching and setup steps for ONNX Runtime
build.rsupdated with iOS-specific linker configuration for ONNX Runtime static library- iOS TTS dependencies added to
Cargo.tomlwith appropriate feature flags
Rust Backend:
lib.rsupdated to enable TTS module for iOS (previously desktop-only) with proper conditional compilationtts.rsupdated with iOS-specific path handling using~/Documents/tts_modelsdirectory- TTS commands added to iOS invoke handler (download, load, synthesize, unload, delete)
Frontend:
TTSContext.tsxupdated to enable TTS on iOS using platform detection utilities
Critical Issues Found
Build-Breaking Issues:
- Filename mismatch in download script - The script downloads
onnxruntime.afrom HuggingFace but saves it aslibonnxruntime.a, which will cause downloads to fail - Invalid Cargo config tables - The GitHub Actions workflows generate Cargo config with invalid table names like
[target.aarch64-apple-ios.onnxruntime]which Cargo will ignore - Inconsistent verification - The workflows verify
libonnxruntime.aexists but the script savesonnxruntime.a
These issues will prevent the iOS build from succeeding until fixed.
Architecture
The implementation follows a solid architecture:
- TTS models (~264MB) are downloaded on-demand at runtime, stored in iOS Documents directory
- ONNX Runtime static library (~100MB+) is downloaded at build time and cached in GitHub Actions
- The same TTS engine code is reused for both desktop and iOS via conditional compilation
- Platform detection properly identifies iOS to enable TTS functionality
Confidence Score: 1/5
- This PR has critical build-breaking issues that will prevent iOS builds from succeeding
- Multiple critical logical errors were found that will cause build failures: (1) filename mismatch in the download script where it downloads onnxruntime.a but saves as libonnxruntime.a, (2) invalid Cargo configuration table names that will be ignored, (3) inconsistent file verification. These issues demonstrate the code was not tested on a real iOS build. While the overall architecture is sound and the implementation approach is good, these errors must be fixed before the PR can work.
- Pay close attention to frontend/src-tauri/scripts/setup-ios-onnxruntime.sh (critical filename bugs), .github/workflows/mobile-build.yml and .github/workflows/testflight-on-comment.yml (invalid Cargo config)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 1/5 | Critical filename mismatch - downloads onnxruntime.a but saves as libonnxruntime.a, causing download failures |
| .github/workflows/mobile-build.yml | 2/5 | Invalid Cargo config table names and filename mismatches that will prevent builds from working |
| .github/workflows/testflight-on-comment.yml | 2/5 | Same issues as mobile-build.yml - invalid Cargo config and filename mismatches |
| frontend/src-tauri/build.rs | 3/5 | iOS build configuration added with minor inconsistency in ORT_LIB_LOCATION path between build.rs and workflows |
| frontend/src-tauri/Cargo.toml | 4/5 | iOS TTS dependencies added correctly with appropriate feature flags for ort crate |
| frontend/src-tauri/src/lib.rs | 4/5 | iOS TTS support properly integrated with conditional compilation, TTS state management, and invoke handlers |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Script as setup-ios-onnxruntime.sh
participant HF as HuggingFace
participant Build as build.rs
participant Cargo as Cargo Build
participant ORT as ONNX Runtime
participant TTS as TTS Engine
participant iOS as iOS Device
Note over GHA,HF: Build-time Setup
GHA->>GHA: Cache check for onnxruntime-ios
alt Cache miss
GHA->>Script: Execute setup script
Script->>HF: Download xcframework (Info.plist, headers)
Script->>HF: Download ios-arm64/onnxruntime.a
Script->>HF: Download ios-arm64_x86_64-simulator/onnxruntime.a
Script->>GHA: Save to onnxruntime-ios/
GHA->>GHA: Cache onnxruntime-ios directory
end
GHA->>GHA: Generate .cargo/config.toml with paths
GHA->>GHA: Set ORT_LIB_LOCATION env var
GHA->>Build: Invoke Tauri iOS build
Build->>Build: Detect target_os = ios
Build->>Build: Set rustc-link-search to arch-specific path
Build->>Build: Set rustc-link-lib=static=onnxruntime
Build->>Build: Link iOS frameworks (Foundation, Accelerate)
Build->>Cargo: Build with iOS target
Cargo->>ORT: Link pre-built ONNX Runtime static lib
Cargo->>GHA: Produce iOS .ipa
Note over TTS,iOS: Runtime Usage
iOS->>TTS: User requests TTS
TTS->>TTS: Check status (models_downloaded?)
alt Models not downloaded
TTS->>HF: Download TTS models (~264MB)
TTS->>iOS: Save to ~/Documents/tts_models/
end
TTS->>ORT: Load ONNX models (duration, encoder, estimator, vocoder)
TTS->>TTS: Load voice style (F2.json)
iOS->>TTS: Synthesize text
TTS->>TTS: Preprocess text (remove markdown, normalize)
TTS->>ORT: Run duration predictor
TTS->>ORT: Run text encoder
TTS->>ORT: Run vector estimator (denoising loop)
TTS->>ORT: Run vocoder
TTS->>iOS: Return audio as base64 WAV
iOS->>iOS: Play audio via Web Audio API
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" |
There was a problem hiding this comment.
The script downloads onnxruntime.a from HuggingFace but saves it as libonnxruntime.a. The remote file is named onnxruntime.a (without the lib prefix), but the script saves it with the lib prefix. This will cause the download to fail because the URL points to a file named onnxruntime.a, not libonnxruntime.a.
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 62:63
Comment:
The script downloads `onnxruntime.a` from HuggingFace but saves it as `libonnxruntime.a`. The remote file is named `onnxruntime.a` (without the `lib` prefix), but the script saves it with the `lib` prefix. This will cause the download to fail because the URL points to a file named `onnxruntime.a`, not `libonnxruntime.a`.
```suggestion
curl -L -o "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64/onnxruntime.a"
```
How can I resolve this? If you propose a fix, please make it concise.| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | ||
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
There was a problem hiding this comment.
Same issue here - the script downloads onnxruntime.a from HuggingFace but saves it as libonnxruntime.a. This will cause the download to fail.
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" | |
| curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" \ | |
| "$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 66:67
Comment:
Same issue here - the script downloads `onnxruntime.a` from HuggingFace but saves it as `libonnxruntime.a`. This will cause the download to fail.
```suggestion
curl -L -o "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" \
"$HF_BASE_URL/$ORT_VERSION/onnxruntime.xcframework/ios-arm64_x86_64-simulator/onnxruntime.a"
```
How can I resolve this? If you propose a fix, please make it concise.| ls -lh "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" | ||
| ls -lh "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" |
There was a problem hiding this comment.
These ls commands reference libonnxruntime.a but after fixing the download issue above, the files will be named onnxruntime.a (without the lib prefix).
| ls -lh "$XCFRAMEWORK_DIR/ios-arm64/libonnxruntime.a" | |
| ls -lh "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/libonnxruntime.a" | |
| ls -lh "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a" | |
| ls -lh "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 77:78
Comment:
These ls commands reference `libonnxruntime.a` but after fixing the download issue above, the files will be named `onnxruntime.a` (without the `lib` prefix).
```suggestion
ls -lh "$XCFRAMEWORK_DIR/ios-arm64/onnxruntime.a"
ls -lh "$XCFRAMEWORK_DIR/ios-arm64_x86_64-simulator/onnxruntime.a"
```
How can I resolve this? If you propose a fix, please make it concise.| timeout-minutes: 90 | ||
|
|
||
| - name: Verify ONNX Runtime files | ||
| run: | |
There was a problem hiding this comment.
This verification step expects libonnxruntime.a, but the download script saves files as onnxruntime.a (without the lib prefix). After fixing the script, update this to match:
| run: | | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/onnxruntime.a || echo "File not found or not a valid archive" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 76:76
Comment:
This verification step expects `libonnxruntime.a`, but the download script saves files as `onnxruntime.a` (without the `lib` prefix). After fixing the script, update this to match:
```suggestion
file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/onnxruntime.a || echo "File not found or not a valid archive"
```
How can I resolve this? If you propose a fix, please make it concise.| timeout-minutes: 90 | ||
|
|
||
| - name: Verify ONNX Runtime files | ||
| run: | |
There was a problem hiding this comment.
Same issue as in mobile-build.yml - this expects libonnxruntime.a but the script saves onnxruntime.a:
| run: | | |
| file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/onnxruntime.a || echo "File not found or not a valid archive" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 134:134
Comment:
Same issue as in mobile-build.yml - this expects `libonnxruntime.a` but the script saves `onnxruntime.a`:
```suggestion
file ${{ github.workspace }}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64/onnxruntime.a || echo "File not found or not a valid archive"
```
How can I resolve this? If you propose a fix, please make it concise.| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our pre-built library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] |
There was a problem hiding this comment.
The Cargo config table names [target.aarch64-apple-ios.onnxruntime], [target.aarch64-apple-ios-sim.onnxruntime], and [target.x86_64-apple-ios.onnxruntime] are not valid Cargo configuration syntax.
Cargo config only supports specific known table names under [target.<triple>]. The .onnxruntime suffix is not a recognized table and will be ignored by Cargo, meaning these linker settings will have no effect.
If the intent is to configure linking for the ort crate, this approach won't work. The linker flags in build.rs (which uses cargo:rustc-link-search and cargo:rustc-link-lib) are the correct approach and should be sufficient. This entire config generation step may be unnecessary.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 88:98
Comment:
The Cargo config table names `[target.aarch64-apple-ios.onnxruntime]`, `[target.aarch64-apple-ios-sim.onnxruntime]`, and `[target.x86_64-apple-ios.onnxruntime]` are not valid Cargo configuration syntax.
Cargo config only supports specific known table names under `[target.<triple>]`. The `.onnxruntime` suffix is not a recognized table and will be ignored by Cargo, meaning these linker settings will have no effect.
If the intent is to configure linking for the `ort` crate, this approach won't work. The linker flags in `build.rs` (which uses `cargo:rustc-link-search` and `cargo:rustc-link-lib`) are the correct approach and should be sufficient. This entire config generation step may be unnecessary.
How can I resolve this? If you propose a fix, please make it concise.| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our pre-built library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] |
There was a problem hiding this comment.
Same issue as mobile-build.yml - these Cargo config table names with .onnxruntime suffix are not valid and will be ignored by Cargo. The linker configuration in build.rs should be sufficient.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 146:156
Comment:
Same issue as mobile-build.yml - these Cargo config table names with `.onnxruntime` suffix are not valid and will be ignored by Cargo. The linker configuration in `build.rs` should be sufficient.
How can I resolve this? If you propose a fix, please make it concise.| println!("cargo:rustc-link-lib=framework=Accelerate"); | ||
|
|
||
| // Set ORT_LIB_LOCATION for the ort crate | ||
| println!("cargo:rustc-env=ORT_LIB_LOCATION={}", ort_dir); |
There was a problem hiding this comment.
The ORT_LIB_LOCATION is set to ort_dir (the base onnxruntime-ios directory), but the GitHub Actions workflow sets it to the architecture-specific path (ios-arm64). This inconsistency could cause issues depending on what the ort crate expects.
The workflow's environment variable will override this build script value, but during local development builds this could cause confusion. Consider whether ORT_LIB_LOCATION should point to the base directory or the architecture-specific directory, and make it consistent across build.rs and the workflows.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 26:26
Comment:
The `ORT_LIB_LOCATION` is set to `ort_dir` (the base `onnxruntime-ios` directory), but the GitHub Actions workflow sets it to the architecture-specific path (`ios-arm64`). This inconsistency could cause issues depending on what the `ort` crate expects.
The workflow's environment variable will override this build script value, but during local development builds this could cause confusion. Consider whether `ORT_LIB_LOCATION` should point to the base directory or the architecture-specific directory, and make it consistent across build.rs and the workflows.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech (TTS) support for iOS using ONNX Runtime, enabling the Supertonic TTS model to run on-device. The implementation mirrors the existing desktop TTS functionality.
Key Changes:
- Rust Backend: Enables TTS module compilation for iOS, adds iOS-specific dependencies (ort with std/ndarray features), and uses
~/Documents/tts_modelsfor model storage on iOS - Build System: Adds build.rs configuration for linking ONNX Runtime xcframework, with separate paths for simulator vs device builds
- CI/CD: GitHub Actions workflows now build ONNX Runtime 1.20.1 from source (cached), generate cargo config with absolute paths, and set environment variables for linking
- Frontend: Updates TTSContext to enable TTS on iOS platforms
Critical Issue Found:
The lib.rs file contains a blocking bug where Android and iOS app configurations both create a variable named app, causing the Android configuration (lines 271-289) to be completely shadowed by the iOS configuration (lines 293-317). This will break Android builds.
Technical Approach:
- ONNX Runtime is built from source via
build-ios-onnxruntime.shduring CI, creating a universal xcframework - Static linking is configured through both build.rs and a generated
.cargo/config.toml - TTS models (~264MB) are downloaded on-demand to iOS Documents directory
Confidence Score: 0/5
- NOT SAFE to merge - contains critical bug that breaks Android builds
- The PR contains a P0 blocking issue in lib.rs where the Android app configuration is shadowed by the iOS configuration, causing both blocks to try to create the same
appvariable. This will cause Android builds to fail because iOS TTS commands won't exist on Android. The shadowing bug must be fixed before merge. - frontend/src-tauri/src/lib.rs (critical cfg block shadowing bug)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/src/lib.rs | 0/5 | Adds iOS TTS support by enabling TTS module and commands. CRITICAL BUG: Android and iOS app configurations shadow each other, breaking Android builds. |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling for TTS models using ~/Documents directory, appropriate for iOS file system. |
| frontend/src-tauri/build.rs | 4/5 | Adds iOS ONNX Runtime linking configuration. ORT_LIB_LOCATION value differs from workflows, may cause confusion but likely functional. |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies with appropriate ort features (std, ndarray) and disabled default features. |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Updates TTS availability check to include iOS platforms alongside desktop. |
| .github/workflows/mobile-build.yml | 4/5 | Adds ONNX Runtime build from source with caching, cargo config generation, and ORT_LIB_LOCATION env var. Comprehensive build setup. |
| .github/workflows/testflight-on-comment.yml | 4/5 | Mirrors mobile-build.yml changes for TestFlight builds. Identical ONNX Runtime setup for consistency. |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 5/5 | New script to build ONNX Runtime from source for iOS, creating xcframework with device and simulator libraries. |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant ONNX as ONNX Runtime Repo
participant Cargo as Cargo Build
participant iOS as iOS App
participant TTS as TTS Module
participant Models as HuggingFace
Note over GHA,ONNX: Build Phase (CI)
GHA->>GHA: Check cache for ONNX Runtime
alt Cache miss
GHA->>Build: Execute build-ios-onnxruntime.sh
Build->>ONNX: Clone v1.20.1
Build->>Build: Build for ios-arm64
Build->>Build: Build for ios-arm64_x86_64-simulator
Build->>Build: Create xcframework
Build-->>GHA: xcframework ready
end
GHA->>GHA: Generate .cargo/config.toml
GHA->>GHA: Set ORT_LIB_LOCATION env
GHA->>Cargo: cargo build (via tauri ios build)
Note over Cargo,TTS: Compile Time
Cargo->>Cargo: Read build.rs
Cargo->>Cargo: Link static libonnxruntime.a
Cargo->>Cargo: Compile with iOS TTS support
Cargo-->>GHA: iOS IPA created
Note over iOS,Models: Runtime
iOS->>TTS: User initiates TTS
TTS->>TTS: Check ~/Documents/tts_models
alt Models not present
TTS->>Models: Download Supertonic models (~264MB)
Models-->>TTS: Models downloaded
TTS->>TTS: Save to ~/Documents/tts_models
end
TTS->>TTS: Load ONNX models via ort crate
TTS->>TTS: Synthesize speech
TTS-->>iOS: Audio playback
| @@ -279,6 +288,34 @@ pub fn run() { | |||
| }) | |||
| .plugin(tauri_plugin_updater::Builder::new().build()); | |||
|
|
|||
| // iOS-specific configuration (with TTS) | |||
| #[cfg(all(not(desktop), target_os = "ios"))] | |||
| let app = builder | |||
| .invoke_handler(tauri::generate_handler![ | |||
| pdf_extractor::extract_document_content, | |||
| tts::tts_get_status, | |||
| tts::tts_download_models, | |||
| tts::tts_load_models, | |||
| tts::tts_synthesize, | |||
| tts::tts_unload_models, | |||
| tts::tts_delete_models, | |||
| ]) | |||
| .setup(|app| { | |||
| // Set up the deep link handler for mobile | |||
| let app_handle = app.handle().clone(); | |||
|
|
|||
| // Register deep link handler - note that iOS does not support runtime registration | |||
| // but the handler for incoming URLs still works | |||
| app.deep_link().on_open_url(move |event| { | |||
| if let Some(url) = event.urls().first() { | |||
| handle_deep_link_event(url.as_ref(), &app_handle); | |||
| } | |||
| }); | |||
|
|
|||
| Ok(()) | |||
| }) | |||
| .plugin(tauri_plugin_updater::Builder::new().build()); | |||
|
|
|||
There was a problem hiding this comment.
[P0] Android app configuration is shadowed and never runs. Both Android (line 271) and iOS (line 293) configurations create a variable named app, causing the Android configuration to be completely overwritten. On Android builds, this will cause compilation failure because iOS-specific TTS commands won't exist.
The iOS block at line 292 should use #[cfg(target_os = "ios")] instead of #[cfg(all(not(desktop), target_os = "ios"))] since the outer #[cfg(not(desktop))] already excludes desktop. This would prevent both blocks from trying to create app.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/src/lib.rs
Line: 269:318
Comment:
[P0] Android app configuration is shadowed and never runs. Both Android (line 271) and iOS (line 293) configurations create a variable named `app`, causing the Android configuration to be completely overwritten. On Android builds, this will cause compilation failure because iOS-specific TTS commands won't exist.
The iOS block at line 292 should use `#[cfg(target_os = "ios")]` instead of `#[cfg(all(not(desktop), target_os = "ios"))]` since the outer `#[cfg(not(desktop))]` already excludes desktop. This would prevent both blocks from trying to create `app`.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @frontend/src-tauri/scripts/build-ios-onnxruntime.sh:
- Around line 220-232: The Info.plist generation currently unconditionally lists
x86_64 under SupportedArchitectures even if the x86_64 simulator build fails;
modify the build-ios-onnxruntime.sh flow so that the simulator build step sets a
boolean flag on failure (the code path that currently only logs a warning for
the x86_64 simulator build) and then use that flag when emitting the <array> for
SupportedArchitectures: omit the <string>x86_64</string> entry if the x86_64
build failed, or alternatively append a clear summary warning to the build
output indicating the Info.plist contains only arm64; ensure the flag is
referenced where the Info.plist snippet with SupportedArchitectures is written
so the plist accurately reflects the actual built libs.
- Around line 124-130: The simulator arm64 lookup assigns IOS_SIM_ARM64_LIB but
lacks the error check; mirror the device block's behavior by validating
IOS_SIM_ARM64_LIB after the find (and fallback) and, if empty, log a clear error
(e.g., "Could not find iOS simulator arm64 lib: libonnxruntime.a") and exit
non‑zero so the script fails fast before lipo/cp; update the echo to only run
when IOS_SIM_ARM64_LIB is set.
🧹 Nitpick comments (2)
frontend/src-tauri/scripts/build-ios-onnxruntime.sh (2)
14-14: Consider stricter error handling withset -euo pipefail.Using
set -ealone may miss failures in pipelines and unbound variable references. Adding-ucatches typos and-o pipefailensures pipeline failures propagate.Suggested improvement
-set -e +set -euo pipefail
184-192: Header copy may silently fail with confusing downstream errors.Line 184's
find ... | head -n 1 | xargs dirnamewill produce.if no file is found (empty input toxargs), potentially causing the header copy to silently do nothing. Consider adding a check.Suggested improvement
# Copy headers -HEADER_DIR=$(find build -name "onnxruntime_c_api.h" -type f | head -n 1 | xargs dirname) -if [ -n "$HEADER_DIR" ]; then +HEADER_FILE=$(find build -name "onnxruntime_c_api.h" -type f | head -n 1) +if [ -n "$HEADER_FILE" ]; then + HEADER_DIR=$(dirname "$HEADER_FILE") cp "${HEADER_DIR}"/*.h "${XCFRAMEWORK_DIR}/Headers/" 2>/dev/null || true fi
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.ymlfrontend/src-tauri/.gitignorefrontend/src-tauri/scripts/build-ios-onnxruntime.sh
✅ Files skipped from review due to trivial changes (1)
- frontend/src-tauri/.gitignore
🚧 Files skipped from review as they are similar to previous changes (2)
- .github/workflows/mobile-build.yml
- .github/workflows/testflight-on-comment.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-android
🔇 Additional comments (4)
frontend/src-tauri/scripts/build-ios-onnxruntime.sh (4)
47-62: LGTM!The clone and checkout logic correctly handles both fresh clones and updates to existing repositories. The
--depth 1 --recursiveclone is appropriate for CI builds to minimize download size.
92-105: LGTM!Good defensive fallback logic to find the library in alternate locations, with helpful debug output if the build fails.
132-158: LGTM!The x86_64 simulator build correctly treats a missing library as a warning rather than an error, since arm64-only simulator support is acceptable for Apple Silicon workflows. The downstream logic at lines 174-181 properly handles both cases.
242-258: LGTM!Clear build summary with helpful debugging information including library sizes and a symbol verification command.
ONNX Runtime 1.20.1 has a stale Eigen dependency hash that no longer matches GitLab's regenerated archive. Upgrading to 1.22.0 which has updated dependency hashes. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
GitLab archives are regenerated periodically, causing hash mismatches with older ONNX Runtime versions. Using the latest release (1.22.2) which should have the most current dependency hashes. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
ONNX Runtime builds multiple component static libraries instead of a single libonnxruntime.a. We now use libtool to combine them all into one archive for easier linking. Also simplified to only build arm64 simulator (skipping x86_64) since GitHub Actions runners use Apple Silicon. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Transient network errors (DNS resolution failures) can cause the ONNX Runtime clone to fail. Added retry logic with 3 attempts and 10 second delays between retries. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS TTS support by integrating ONNX Runtime 1.22.2, enabling the Supertonic TTS model to run on-device.
Key Changes:
- Build System: Adds
build-ios-onnxruntime.shto build ONNX Runtime from source with all dependencies statically linked. GitHub Actions caches the ~90min build for reuse. - Linker Configuration:
build.rsconfigures iOS-specific linker paths for the ONNX Runtime xcframework, linking Foundation and Accelerate frameworks. - Rust Backend: Enables the
ttsmodule for iOS with platform-specific model storage in~/Documents/tts_models(iOS sandboxing requirement). - Frontend: Updates
TTSContext.tsxto detect iOS platform and enable TTS UI/functionality. - Cargo Dependencies: Adds iOS-specific
ortdependency withdefault-features = falseto prevent automatic binary downloads.
Architecture:
The implementation mirrors the desktop TTS approach: users download ~264MB of models on-demand, which are then loaded into memory for synthesis. The ONNX Runtime library is built from source to ensure all dependencies (Abseil, protobuf, etc.) are statically linked into a single .a file per architecture.
iOS-Specific Adaptations:
- Model storage uses
~/Documents/tts_modelsinstead of system data directories - Static library linking via xcframework structure (device + simulator)
- Build process integrated into CI/CD with caching
Confidence Score: 3/5
- Generally safe but has a path mismatch bug that will cause simulator build failures
- The implementation is well-structured and follows proper iOS patterns, but contains a critical path inconsistency between build.rs and the build script that will cause linker failures for simulator builds. The Cargo config sections in workflows also use non-standard syntax that Cargo will ignore (though this may not break builds if build.rs handles linking correctly).
- frontend/src-tauri/build.rs (simulator path mismatch), .github/workflows/*.yml (non-standard Cargo config syntax)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 3/5 | Adds ONNX Runtime build/cache steps and Cargo config generation with non-standard target sections that Cargo will ignore |
| .github/workflows/testflight-on-comment.yml | 3/5 | Mirrors mobile-build.yml with same ONNX Runtime setup and Cargo config issues |
| frontend/src-tauri/.gitignore | 5/5 | Adds ignore patterns for ONNX Runtime iOS build artifacts and generated cargo config |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies with proper feature flags to disable download-binaries |
| frontend/src-tauri/build.rs | 4/5 | Adds iOS linker configuration for ONNX Runtime with simulator path inconsistency |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 5/5 | New script to build ONNX Runtime 1.22.2 from source for iOS, creates xcframework with combined static libraries |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 5/5 | New script to download pre-built ONNX Runtime 1.20.1 from HuggingFace (not used by workflows) |
| frontend/src-tauri/src/lib.rs | 5/5 | Enables TTS module for iOS, adds iOS-specific app initialization with TTS state management and invoke handlers |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling using ~/Documents/tts_models for model storage |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Updates platform detection to enable TTS on iOS in addition to desktop |
| frontend/bun.lock | 5/5 | Lock file update, likely from dependency changes |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant Cargo as Cargo Build
participant BuildRS as build.rs
participant ORT as ONNX Runtime
participant App as iOS App
Note over GHA: iOS Build Pipeline
GHA->>GHA: Cache check (1.22.2-v1)
alt Cache Miss
GHA->>Build: Run build script
Build->>Build: Clone ONNX Runtime 1.22.2
Build->>Build: Build ios-arm64 static lib
Build->>Build: Build ios-arm64-simulator lib
Build->>Build: Create xcframework structure
Build-->>GHA: xcframework ready
end
GHA->>GHA: Configure Cargo config.toml
Note over GHA: Sets [target.*.onnxruntime]<br/>(non-standard, ignored by Cargo)
GHA->>Cargo: bun tauri ios build
Cargo->>BuildRS: Execute build.rs
BuildRS->>BuildRS: Detect iOS target
BuildRS->>BuildRS: Set rustc-link-search
BuildRS->>BuildRS: Set ORT_LIB_LOCATION
BuildRS-->>Cargo: Link configuration
Cargo->>ORT: Link static library
Note over ORT: Uses ios-arm64 or<br/>ios-arm64-simulator
ORT-->>Cargo: Linked binary
Cargo->>App: Build iOS app
App->>App: TTS module available
Note over App: Models stored in<br/>~/Documents/tts_models
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | ||
| } else { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) |
There was a problem hiding this comment.
[P2] Simulator path inconsistency: build.rs uses ios-arm64_x86_64-simulator for sim/x86_64 targets, but build-ios-onnxruntime.sh creates only ios-arm64-simulator. This mismatch will cause linker failures when building for x86_64 simulator. Either update build.rs to use ios-arm64-simulator or update the build script to create the ios-arm64_x86_64-simulator directory.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 11:14
Comment:
[P2] Simulator path inconsistency: `build.rs` uses `ios-arm64_x86_64-simulator` for sim/x86_64 targets, but `build-ios-onnxruntime.sh` creates only `ios-arm64-simulator`. This mismatch will cause linker failures when building for x86_64 simulator. Either update `build.rs` to use `ios-arm64-simulator` or update the build script to create the `ios-arm64_x86_64-simulator` directory.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS TTS support using ONNX Runtime, building from source (v1.22.2) and enabling the Supertonic TTS model to run on-device on iOS. The implementation mirrors the existing desktop TTS functionality with iOS-specific adjustments for file paths and dependencies.
What Changed
Core Implementation:
- Added iOS-specific TTS dependencies to Cargo.toml (ort, ndarray, etc.)
- Modified build.rs to link ONNX Runtime xcframework for iOS builds
- Updated lib.rs to enable TTS module for iOS (was desktop-only)
- Modified tts.rs to use iOS Documents directory for model storage
- Updated frontend TTSContext.tsx to enable TTS on iOS devices
Build Infrastructure:
- Added build-ios-onnxruntime.sh to build ONNX Runtime 1.22.2 from source
- Added setup-ios-onnxruntime.sh (downloads pre-built 1.20.1, appears unused in CI)
- Modified GitHub Actions workflows to build/cache ONNX Runtime and configure Cargo
- Added .gitignore entries for ONNX Runtime build artifacts
Critical Issues Found
🔴 Path Mismatch Bug (Will Break Simulator Builds):
The build-ios-onnxruntime.sh script creates the xcframework with path ios-arm64-simulator, but build.rs looks for ios-arm64_x86_64-simulator. This inconsistency will cause iOS simulator builds to fail with linker errors. Device builds will work, but developers cannot test in the iOS simulator.
🔴 Invalid Cargo Configuration Syntax:
Both workflow files generate Cargo config with [target.aarch64-apple-ios.onnxruntime] sections. The .onnxruntime suffix is not valid Cargo syntax and will be ignored. This means the custom linker paths won't be applied, potentially causing build failures.
Other Issues
- Performance: iOS ndarray missing
rayonfeature (present in desktop version) may cause slower TTS synthesis - Version Confusion: setup-ios-onnxruntime.sh defaults to 1.20.1 while everything else uses 1.22.2
- Documentation: PR description mentions 1.20.1 but actual builds use 1.22.2
Architecture Assessment
The overall approach is sound: using platform-specific conditional compilation, proper iOS sandboxing (Documents directory), and building ONNX Runtime from source to ensure compatibility. The TTS implementation correctly reuses the existing desktop code. However, the critical path mismatch bug must be fixed before this can work on iOS simulator.
Confidence Score: 1/5
- This PR has critical bugs that will break iOS simulator builds and potentially all iOS builds due to invalid Cargo configuration
- Score of 1 (critical issues) reflects two blocking bugs: (1) xcframework path mismatch between build script output and build.rs expectations will cause linker failures for iOS simulator, and (2) invalid Cargo config syntax in workflows means linker paths won't be applied correctly. These are not "potential" issues - they will definitely cause build failures. Device builds might work by accident if the build.rs paths are found, but simulator builds will fail 100% of the time.
- Critical fixes needed in: frontend/src-tauri/build.rs (line 12), .github/workflows/mobile-build.yml (lines 97-107), .github/workflows/testflight-on-comment.yml (lines 155-165). Also review frontend/src-tauri/Cargo.toml for iOS ndarray rayon feature.
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| frontend/src-tauri/build.rs | 1/5 | Critical path mismatch bug: simulator library path points to ios-arm64_x86_64-simulator instead of ios-arm64-simulator, causing iOS simulator builds to fail |
| .github/workflows/mobile-build.yml | 1/5 | Invalid Cargo config syntax with .onnxruntime suffix will be ignored; simulator path inconsistency will cause linker failures |
| .github/workflows/testflight-on-comment.yml | 1/5 | Same issues as mobile-build.yml: invalid Cargo config syntax and simulator path mismatch |
| frontend/src-tauri/Cargo.toml | 3/5 | iOS ndarray missing rayon feature may cause performance degradation compared to desktop; TTS dependencies properly added for iOS |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 4/5 | Build script creates ios-arm64-simulator directory (not ios-arm64_x86_64-simulator), causing path mismatch with other files; otherwise well-structured with retry logic |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant Cache as Actions Cache
participant BuildRS as build.rs
participant Cargo as Cargo Build
participant XCF as xcframework
Note over GHA,XCF: iOS TTS Build Flow
GHA->>Cache: Check cache for onnxruntime-ios-built-1.22.2-v1
alt Cache Hit
Cache-->>GHA: Restore cached xcframework
else Cache Miss
GHA->>Build: Execute build-ios-onnxruntime.sh 1.22.2
Build->>Build: Clone ONNX Runtime v1.22.2
Build->>Build: Build for ios-arm64 (device)
Build->>Build: Build for ios-arm64-simulator
Build->>XCF: Create xcframework at ios-arm64-simulator/
XCF-->>Build: xcframework created
Build-->>GHA: Build complete
GHA->>Cache: Cache xcframework for future builds
end
GHA->>GHA: Generate .cargo/config.toml
Note over GHA: ⚠️ BUG: Uses invalid [target.*.onnxruntime] syntax
Note over GHA: ⚠️ BUG: Points to ios-arm64-simulator (correct path from build script)
GHA->>BuildRS: Invoke build.rs during cargo build
BuildRS->>BuildRS: Check TARGET env var
alt Simulator Build
Note over BuildRS: ⚠️ BUG: Looks for ios-arm64_x86_64-simulator
BuildRS->>XCF: Search for ios-arm64_x86_64-simulator/libonnxruntime.a
XCF-->>BuildRS: ❌ File not found (actual path is ios-arm64-simulator)
BuildRS-->>Cargo: ❌ Linker error - library not found
else Device Build
BuildRS->>XCF: Search for ios-arm64/libonnxruntime.a
XCF-->>BuildRS: ✅ File found
BuildRS->>Cargo: Link libonnxruntime.a + Accelerate + Foundation
Cargo->>Cargo: Compile Rust code with TTS
Cargo-->>GHA: ✅ Build succeeds for device
end
Note over GHA,Cargo: Result: Device builds work, simulator builds fail
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) |
There was a problem hiding this comment.
The simulator xcframework path ios-arm64_x86_64-simulator in build.rs does not match the actual path created by build-ios-onnxruntime.sh which creates ios-arm64-simulator. This will cause build failures when building for iOS simulator.
Impact: iOS simulator builds will fail with a linker error because the library cannot be found at this path.
Root cause: The build-ios-onnxruntime.sh script (line 205) creates the directory as ios-arm64-simulator, but this build.rs expects ios-arm64_x86_64-simulator (matching the setup script but not the build script).
Fix needed: Change this line to:
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir) |
Also update the GitHub workflows (mobile-build.yml lines 102, 106 and testflight-on-comment.yml lines 160, 164) to use ios-arm64-simulator instead of ios-arm64-simulator in the cargo config generation.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 12:12
Comment:
The simulator xcframework path `ios-arm64_x86_64-simulator` in build.rs does not match the actual path created by `build-ios-onnxruntime.sh` which creates `ios-arm64-simulator`. This will cause build failures when building for iOS simulator.
**Impact**: iOS simulator builds will fail with a linker error because the library cannot be found at this path.
**Root cause**: The `build-ios-onnxruntime.sh` script (line 205) creates the directory as `ios-arm64-simulator`, but this build.rs expects `ios-arm64_x86_64-simulator` (matching the setup script but not the build script).
**Fix needed**: Change this line to:
```suggestion
format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir)
```
Also update the GitHub workflows (mobile-build.yml lines 102, 106 and testflight-on-comment.yml lines 160, 164) to use `ios-arm64-simulator` instead of `ios-arm64-simulator` in the cargo config generation.
How can I resolve this? If you propose a fix, please make it concise.| # We disable download-binaries and copy-dylibs since we link our own xcframework | ||
| # Need "std" for Error trait impl and file operations, "ndarray" for tensor creation | ||
| ort = { version = "2.0.0-rc.10", default-features = false, features = ["std", "ndarray"] } | ||
| ndarray = { version = "0.16" } |
There was a problem hiding this comment.
The iOS version of ndarray is missing the "rayon" feature that is included in the desktop version (line 46). This inconsistency could cause performance degradation on iOS since parallel operations won't be available.
The desktop version has:
ndarray = { version = "0.16", features = ["rayon"] }But the iOS version only has:
ndarray = { version = "0.16" }Impact: TTS synthesis on iOS may be significantly slower than on desktop due to lack of parallel processing via rayon.
| ndarray = { version = "0.16" } | |
| ndarray = { version = "0.16", features = ["rayon"] } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/Cargo.toml
Line: 62:62
Comment:
The iOS version of ndarray is missing the "rayon" feature that is included in the desktop version (line 46). This inconsistency could cause performance degradation on iOS since parallel operations won't be available.
The desktop version has:
```toml
ndarray = { version = "0.16", features = ["rayon"] }
```
But the iOS version only has:
```toml
ndarray = { version = "0.16" }
```
**Impact**: TTS synthesis on iOS may be significantly slower than on desktop due to lack of parallel processing via rayon.
```suggestion
ndarray = { version = "0.16", features = ["rayon"] }
```
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
The cargo config sections use an invalid format: [target.aarch64-apple-ios.onnxruntime]. This was already noted in previous review threads. The .onnxruntime suffix is not a valid Cargo config section and will be ignored by Cargo.
Standard Cargo only supports [target.<triple>] sections. The correct format should be:
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Additionally, line 106 has the wrong path - it should point to ios-arm64-simulator not ios-arm64-simulator (matching the build-ios-onnxruntime.sh script output).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 97:107
Comment:
The cargo config sections use an invalid format: `[target.aarch64-apple-ios.onnxruntime]`. This was already noted in previous review threads. The `.onnxruntime` suffix is not a valid Cargo config section and will be ignored by Cargo.
Standard Cargo only supports `[target.<triple>]` sections. The correct format should be:
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
Additionally, line 106 has the wrong path - it should point to `ios-arm64-simulator` not `ios-arm64-simulator` (matching the build-ios-onnxruntime.sh script output).
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Same issue as in mobile-build.yml: The cargo config sections use an invalid format with .onnxruntime suffix which will be ignored by Cargo.
The correct format should be:
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Additionally, line 164 has the wrong path - it should point to ios-arm64-simulator (matching the build-ios-onnxruntime.sh script output).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 155:165
Comment:
Same issue as in mobile-build.yml: The cargo config sections use an invalid format with `.onnxruntime` suffix which will be ignored by Cargo.
The correct format should be:
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
Additionally, line 164 has the wrong path - it should point to `ios-arm64-simulator` (matching the build-ios-onnxruntime.sh script output).
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| TAURI_DIR="$(dirname "$SCRIPT_DIR")" | ||
| ORT_VERSION="${ORT_VERSION:-1.20.1}" |
There was a problem hiding this comment.
Version mismatch: This script defaults to ONNX Runtime 1.20.1, but:
- The PR description states version 1.20.1 is being used
- The build-ios-onnxruntime.sh script defaults to 1.22.2 (which is what's actually being built in CI)
- Cargo.toml comments say 1.22.2
- The CI cache key is for 1.22.2
Since the CI workflows use the build-from-source script (build-ios-onnxruntime.sh) and cache version 1.22.2, this setup script is essentially unused but creates confusion about which version is intended.
Recommendation: Either update this to match 1.22.2, or document clearly that this script is for local development only and CI uses the build script.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 10:10
Comment:
Version mismatch: This script defaults to ONNX Runtime 1.20.1, but:
- The PR description states version 1.20.1 is being used
- The build-ios-onnxruntime.sh script defaults to 1.22.2 (which is what's actually being built in CI)
- Cargo.toml comments say 1.22.2
- The CI cache key is for 1.22.2
Since the CI workflows use the build-from-source script (build-ios-onnxruntime.sh) and cache version 1.22.2, this setup script is essentially unused but creates confusion about which version is intended.
**Recommendation**: Either update this to match 1.22.2, or document clearly that this script is for local development only and CI uses the build script.
How can I resolve this? If you propose a fix, please make it concise.The simulator build fails with a linker error: 'building for iOS-simulator, but linking in dylib built for iOS' This is a bug in ONNX Runtime's CMake configuration for iOS simulator where it incorrectly uses the iPhoneOS SDK's libiconv instead of the iPhoneSimulator SDK's libiconv. For TestFlight/App Store deployment, only the device (arm64) build is needed anyway. Local development can use desktop or physical devices. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech support for iOS using ONNX Runtime 1.22.2, enabling the Supertonic TTS model to run on-device. The implementation mirrors the desktop version with appropriate iOS-specific adaptations.
Key Changes:
- Builds ONNX Runtime 1.22.2 from source for iOS (device only, simulator build skipped due to known CMake bug)
- Adds iOS-specific dependencies in Cargo.toml matching desktop TTS configuration
- Implements iOS path handling using
~/Documents/tts_modelsfor model storage - Updates frontend to enable TTS on iOS platforms
- Configures GitHub Actions to cache built ONNX Runtime libraries
Critical Issues Found:
The implementation has path inconsistencies between build scripts, build.rs, and GitHub Actions workflows. The build-ios-onnxruntime.sh script creates a directory named ios-arm64-simulator, while build.rs and the setup-ios-onnxruntime.sh script expect ios-arm64_x86_64-simulator. This mismatch will cause linker failures when building for simulator targets, as the linker won't find the library in the expected location.
Impact:
- Device builds may work (ios-arm64 path is consistent)
- Simulator builds will fail with "library not found" linker errors
- TestFlight/App Store deployment blocked until simulator path issues resolved
The overall architecture is sound - TTS module properly gated for iOS, state management correctly configured, and iOS sandboxing constraints appropriately handled. Once path consistency issues are resolved, this should function as intended.
Confidence Score: 2/5
- Not safe to merge - contains blocking path mismatches that will cause build failures
- Multiple P0 path inconsistencies between build script output (ios-arm64-simulator) and expected paths in build.rs/workflows (ios-arm64_x86_64-simulator) will cause linker failures. While device builds may succeed, simulator builds will definitely fail, blocking local development and potentially CI/CD depending on build configuration.
- frontend/src-tauri/scripts/build-ios-onnxruntime.sh (fix directory names), .github/workflows/mobile-build.yml (fix cargo config paths), .github/workflows/testflight-on-comment.yml (fix cargo config paths)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 3/5 | Adds ONNX Runtime build steps for iOS TTS. Contains path inconsistencies between build script output and cargo config that will cause linker failures for simulator builds. |
| .github/workflows/testflight-on-comment.yml | 3/5 | Mirrors mobile-build.yml changes. Same path inconsistency issues will cause simulator build failures. |
| frontend/bun.lock | 5/5 | Minor lockfile metadata update (adds configVersion field). No functional changes. |
| frontend/src-tauri/.gitignore | 5/5 | Adds ignore patterns for ONNX Runtime build artifacts and generated cargo config. |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies matching desktop configuration. Properly configured with correct ort flags. |
| frontend/src-tauri/build.rs | 3/5 | Adds iOS build configuration for ONNX Runtime linking. Simulator path uses ios-arm64_x86_64-simulator but build-ios-onnxruntime.sh creates ios-arm64-simulator, causing mismatch. |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 4/5 | Builds ONNX Runtime 1.22.2 from source, creating ios-arm64 and ios-arm64-simulator directories. Path naming doesn't match what build.rs expects. |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 4/5 | Downloads pre-built ONNX Runtime from HuggingFace. Creates ios-arm64_x86_64-simulator directory (different naming than build script). Currently unused as workflow uses build script instead. |
| frontend/src-tauri/src/lib.rs | 5/5 | Enables TTS module and commands for iOS, adds iOS-specific app setup with TTS state management. Logic correctly separated between iOS and Android. |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling for TTS models using ~/Documents/tts_models. Implementation is appropriate for iOS sandboxing. |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Updates TTS availability check to include iOS platforms. Correctly uses platform detection utilities. |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant Cache as Actions Cache
participant Cargo as Cargo Build
participant BuildRS as build.rs
participant ORT as ONNX Runtime
GHA->>Cache: Check for onnxruntime-ios cache
alt Cache Miss
GHA->>Build: Execute build script (1.22.2)
Build->>Build: Clone ONNX Runtime repo
Build->>Build: Build for ios-arm64 (device)
Build->>Build: Skip ios-arm64-simulator (CMake bug)
Build->>Build: Create xcframework with<br/>ios-arm64/<br/>ios-arm64-simulator/
Build->>Cache: Store in cache
else Cache Hit
Cache->>GHA: Restore onnxruntime-ios
end
GHA->>GHA: Generate .cargo/config.toml<br/>with ios-arm64-simulator paths
Note over GHA,BuildRS: PATH MISMATCH OCCURS HERE
GHA->>Cargo: cargo-tauri ios build
Cargo->>BuildRS: Execute build.rs
BuildRS->>BuildRS: Set rustc-link-search for<br/>ios-arm64_x86_64-simulator
BuildRS->>Cargo: Return linker flags
alt Device Build (aarch64-apple-ios)
Cargo->>ORT: Link ios-arm64/libonnxruntime.a ✓
Cargo->>GHA: Build succeeds
else Simulator Build (aarch64-apple-ios-sim)
Cargo->>ORT: Search ios-arm64_x86_64-simulator/ ✗
Note over Cargo,ORT: Directory not found!<br/>Actual: ios-arm64-simulator
Cargo->>GHA: Linker error: library not found
end
|
|
||
| mkdir -p "${OUTPUT_DIR}" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64-simulator" |
There was a problem hiding this comment.
[P0] Simulator directory name mismatch will cause linker failures. This creates ios-arm64-simulator but build.rs expects ios-arm64_x86_64-simulator. Change line 172 to: mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator"
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 172:172
Comment:
[P0] Simulator directory name mismatch will cause linker failures. This creates `ios-arm64-simulator` but `build.rs` expects `ios-arm64_x86_64-simulator`. Change line 172 to: `mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator"`
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| # Copy the simulator library (arm64 only for now) | ||
| if [ -n "$IOS_SIM_ARM64_LIB" ] && [ -f "$IOS_SIM_ARM64_LIB" ]; then | ||
| cp "$IOS_SIM_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64-simulator/libonnxruntime.a" |
There was a problem hiding this comment.
[P0] Simulator path mismatch. Change to match expected directory: cp "$IOS_SIM_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator/libonnxruntime.a"
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 180:180
Comment:
[P0] Simulator path mismatch. Change to match expected directory: `cp "$IOS_SIM_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator/libonnxruntime.a"`
How can I resolve this? If you propose a fix, please make it concise.| <key>HeadersPath</key> | ||
| <string>Headers</string> | ||
| <key>LibraryIdentifier</key> | ||
| <string>ios-arm64-simulator</string> |
There was a problem hiding this comment.
[P0] Plist metadata mismatch. Change LibraryIdentifier to: <string>ios-arm64_x86_64-simulator</string> to match actual directory structure.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 222:222
Comment:
[P0] Plist metadata mismatch. Change LibraryIdentifier to: `<string>ios-arm64_x86_64-simulator</string>` to match actual directory structure.
How can I resolve this? If you propose a fix, please make it concise.| <key>SupportedArchitectures</key> | ||
| <array> | ||
| <string>arm64</string> | ||
| </array> |
There was a problem hiding this comment.
[P1] Plist declares both arm64 and x86_64 architectures but script only builds arm64 simulator (line 162 skips simulator). Either build both architectures or update to only list <string>arm64</string>.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 225:228
Comment:
[P1] Plist declares both arm64 and x86_64 architectures but script only builds arm64 simulator (line 162 skips simulator). Either build both architectures or update to only list `<string>arm64</string>`.
How can I resolve this? If you propose a fix, please make it concise.| echo "" | ||
| echo "Static library sizes:" | ||
| ls -lh "${XCFRAMEWORK_DIR}/ios-arm64/libonnxruntime.a" | ||
| ls -lh "${XCFRAMEWORK_DIR}/ios-arm64-simulator/libonnxruntime.a" 2>/dev/null || echo "No simulator library" |
There was a problem hiding this comment.
[P0] Path mismatch in verification. Update to: ls -lh "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator/libonnxruntime.a"
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 256:256
Comment:
[P0] Path mismatch in verification. Update to: `ls -lh "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator/libonnxruntime.a"`
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
[P0] Path mismatch with build script output. The build-ios-onnxruntime.sh creates ios-arm64-simulator but this expects ios-arm64-simulator. If using build script, this should be ios-arm64-simulator (which still needs fixing in build script), or if using setup script, keep as ios-arm64_x86_64-simulator.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 102:102
Comment:
[P0] Path mismatch with build script output. The build-ios-onnxruntime.sh creates `ios-arm64-simulator` but this expects `ios-arm64-simulator`. If using build script, this should be `ios-arm64-simulator` (which still needs fixing in build script), or if using setup script, keep as `ios-arm64_x86_64-simulator`.
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
[P0] Path mismatch. Same issue as line 102 - verify simulator directory name matches actual build output.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 106:106
Comment:
[P0] Path mismatch. Same issue as line 102 - verify simulator directory name matches actual build output.
How can I resolve this? If you propose a fix, please make it concise.
Additional Comments (2)
Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 102:102
Comment:
[P0] Path mismatch with build script output. Same issue as mobile-build.yml - simulator directory name inconsistency.
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 106:106
Comment:
[P0] Path mismatch. Same issue as line 102.
How can I resolve this? If you propose a fix, please make it concise. |
|
@TestFlight build |
|
🚀 TestFlight deployment triggered! Check the Actions tab for progress. |
|
❌ TestFlight deployment failed. Check the workflow logs for details. |
TODO: Remove the push trigger after PR #378 is merged. This is a workaround because issue_comment workflows run from master, so they don't pick up workflow changes from the PR branch. We need to test the full TestFlight flow with the ONNX Runtime changes. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS TTS support by building ONNX Runtime 1.22.2 from source and enabling the TTS module on iOS devices. The implementation mirrors the desktop version with iOS-specific paths (~/Documents/tts_models).
Key Changes:
- Builds ONNX Runtime from source via
build-ios-onnxruntime.shwith caching (90min build) - Adds iOS target dependencies in Cargo.toml with correct feature flags (
std,ndarray) - Enables TTS module compilation and invoke handlers for iOS in lib.rs
- Frontend updated to enable TTS on iOS platform
- GitHub Actions workflows extended with ONNX build steps
Critical Issue Found:
The build script creates directory ios-arm64-simulator but build.rs expects ios-arm64_x86_64-simulator, causing simulator builds to fail with missing library errors.
Architecture:
The implementation uses conditional compilation (#[cfg(target_os = "ios")]) throughout to enable TTS on iOS while maintaining desktop functionality. ONNX Runtime is statically linked with all dependencies bundled to avoid runtime linking issues.
Confidence Score: 1/5
- Not safe to merge - critical path mismatch will cause simulator builds to fail
- There is a critical directory name mismatch between build.rs (expects ios-arm64_x86_64-simulator) and the build script that creates ios-arm64-simulator. This will cause the linker to fail when building for iOS simulator, as it won't find the ONNX Runtime library at the expected path. Device builds may work, but any simulator testing will fail.
- frontend/src-tauri/build.rs - Fix simulator directory path mismatch
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 3/5 | Adds ONNX Runtime caching and build-from-source support for iOS TTS. Contains cargo config syntax issue with .onnxruntime suffix that Cargo will ignore. |
| .github/workflows/testflight-on-comment.yml | 3/5 | Adds testflight-on-comment workflow with ONNX Runtime build support. Same cargo config syntax issue as mobile-build.yml. |
| frontend/src-tauri/Cargo.toml | 5/5 | Adds iOS-specific TTS dependencies with correct feature flags. Clean implementation matching desktop dependencies. |
| frontend/src-tauri/build.rs | 0/5 | Adds iOS ONNX Runtime linking configuration. Critical bug: expects ios-arm64_x86_64-simulator directory but build script creates ios-arm64-simulator. |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 4/5 | Builds ONNX Runtime from source for iOS with retry logic and dependency bundling. Creates ios-arm64-simulator directory (mismatches build.rs expectations). |
| frontend/src-tauri/scripts/setup-ios-onnxruntime.sh | 5/5 | Downloads pre-built ONNX Runtime xcframework from HuggingFace (not used in current workflows). Clean implementation. |
| frontend/src-tauri/src/lib.rs | 5/5 | Enables TTS module for iOS and adds iOS-specific invoke handlers. Clean conditional compilation with proper setup handlers. |
| frontend/src-tauri/src/tts.rs | 5/5 | Adds iOS-specific path handling for TTS models using ~/Documents/tts_models. Clean implementation with proper platform conditionals. |
| frontend/src/services/tts/TTSContext.tsx | 5/5 | Enables TTS support for iOS in frontend by updating platform check. Simple, correct change. |
| frontend/src-tauri/.gitignore | 5/5 | Adds gitignore entries for ONNX Runtime build artifacts and generated cargo config. Appropriate additions. |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Cache as Cache Storage
participant Build as Build Script
participant Cargo as Cargo Build
participant Tauri as Tauri iOS Build
participant TF as TestFlight
Note over GHA,Cache: iOS Build Workflow
GHA->>Cache: Check ONNX Runtime cache
alt Cache Hit
Cache-->>GHA: Restore cached xcframework
else Cache Miss
GHA->>Build: Execute build-ios-onnxruntime.sh
Build->>Build: Clone ONNX Runtime 1.22.2
Build->>Build: Build for iOS arm64
Build->>Build: Combine static libraries
Build->>Build: Create xcframework structure
Build-->>GHA: ios-arm64-simulator directory
GHA->>Cache: Save to cache
end
GHA->>GHA: Configure Cargo with absolute paths
GHA->>Cargo: Set ORT_LIB_LOCATION env var
Note over Cargo,Tauri: Rust Build Phase
Tauri->>Cargo: Build Rust code
Cargo->>Cargo: Process build.rs (iOS config)
Cargo->>Cargo: Look for ios-arm64_x86_64-simulator
Cargo->>Cargo: ❌ Directory not found (mismatch)
Note over GHA,TF: Deployment Phase
Tauri->>Tauri: Build iOS app (if linking succeeds)
Tauri->>GHA: Generate IPA
GHA->>TF: Upload to TestFlight
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) |
There was a problem hiding this comment.
[P0] Directory name mismatch will cause simulator builds to fail. The build script at line 172 creates ios-arm64-simulator but this code expects ios-arm64_x86_64-simulator. Change to:
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 12:12
Comment:
[P0] Directory name mismatch will cause simulator builds to fail. The build script at line 172 creates `ios-arm64-simulator` but this code expects `ios-arm64_x86_64-simulator`. Change to:
```suggestion
format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir)
```
How can I resolve this? If you propose a fix, please make it concise.TODO: Remove the ios-tts condition after PR #378 is merged. This allows us to test the full TestFlight flow on every PR build during iOS TTS development. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
left a comment
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/testflight-on-comment.yml (1)
230-252: Guard “comment back on PR” steps forpushruns (no PR number).
Onpush,needs.check-comment.outputs.pr-numberwill be empty, so these steps can fail and turn a successful build into a failed workflow.Proposed fix
- name: Comment on PR with success - if: success() + if: github.event_name == 'issue_comment' && success() uses: actions/github-script@v7 @@ - name: Comment on PR with failure - if: failure() + if: github.event_name == 'issue_comment' && failure() uses: actions/github-script@v7
🤖 Fix all issues with AI agents
In @.github/workflows/testflight-on-comment.yml:
- Around line 19-21: The workflow currently makes the deploy-testflight job
depend on the check-comment job (job id check-comment), so when a push event
skips check-comment the deploy-testflight job will be skipped too; remove the
needs: check-comment dependency or split the workflow into two paths so
deploy-testflight runs on push independently and only the comment-related steps
are gated by check-comment; specifically, ensure deploy-testflight (the job
named deploy-testflight) does not require check-comment, compute
PR_REF/PR_NUMBER inside a step (detecting github.event_name == 'push' vs
'issue_comment'), and conditionally run the comment-posting steps only when the
event is issue_comment (use the check-comment job or an if that references
github.event_name and the presence of the comment).
- Around line 154-175: Remove the "Configure Cargo for iOS ONNX Runtime" step
that generates a .cargo/config.toml with non-standard `[target.*.onnxruntime]`
tables; they are ignored by Cargo. Instead, delete that generation block (or
replace it with a short explanatory comment) and rely on the existing build.rs
logic that emits the `cargo:rustc-link-search` / `cargo:rustc-link-lib`
directives and the ORT_LIB_LOCATION environment variable consumed by the ort
crate to handle linking.
In @frontend/src-tauri/scripts/build-ios-onnxruntime.sh:
- Around line 154-183: The XCFramework currently declares a simulator slice but
never provides a simulator library, causing an invalid xcframework; change the
script to produce a device-only XCFramework by removing creation/usage of the
ios-arm64-simulator slice and related Info.plist entries when IOS_SIM_ARM64_LIB
is empty: stop creating the "${XCFRAMEWORK_DIR}/ios-arm64-simulator" directory,
skip copying or referencing the simulator lib when IOS_SIM_ARM64_LIB is unset,
and ensure the generated Info.plist (the block that mentions
ios-arm64-simulator) only includes the ios-arm64 slice or is conditionally built
when IOS_SIM_ARM64_LIB exists; alternatively, keep the existing conditional copy
but also conditionally build the Info.plist and directory based on
IOS_SIM_ARM64_LIB so the simulator slice is never declared unless a valid
simulator lib is present.
🧹 Nitpick comments (3)
.github/workflows/testflight-on-comment.yml (1)
21-21: Tighten the trigger phrase matching.
contains(..., 'testflight build')will also match unrelated text (“don’t testflight build yet”). Consider exact/anchored matching (trim + startsWith) or a small regex.frontend/src-tauri/scripts/build-ios-onnxruntime.sh (2)
14-40: Harden bash safety and make header discovery non-fragile.
set -ealone (Line 14) + thefind | head | xargs dirnamepipeline (Line 186) is brittle when no header is found.Proposed fix
-set -e +set -euo pipefail @@ -HEADER_DIR=$(find build -name "onnxruntime_c_api.h" -type f | head -n 1 | xargs dirname) -if [ -n "$HEADER_DIR" ]; then - cp "${HEADER_DIR}"/*.h "${XCFRAMEWORK_DIR}/Headers/" 2>/dev/null || true -fi +HEADER_FILE="$(find build -name "onnxruntime_c_api.h" -type f | head -n 1 || true)" +if [ -n "${HEADER_FILE}" ]; then + HEADER_DIR="$(dirname "${HEADER_FILE}")" + cp "${HEADER_DIR}"/*.h "${XCFRAMEWORK_DIR}/Headers/" 2>/dev/null || true +fiAlso applies to: 186-190
129-144:libtoolinvocation may hit arg-length limits; also prefer portable grep.
You pass a potentially huge list of.afiles directly tolibtool(Line 143), and thegrep -v "gtest\|gmock"regex is less portable thangrep -Eon macOS/BSD grep.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.ymlfrontend/src-tauri/scripts/build-ios-onnxruntime.sh
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-01-08T17:09:40.432Z
Learnt from: AnthonyRonning
Repo: OpenSecretCloud/Maple PR: 372
File: frontend/src-tauri/Cargo.toml:9-9
Timestamp: 2026-01-08T17:09:40.432Z
Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates.
Applied to files:
.github/workflows/mobile-build.yml.github/workflows/testflight-on-comment.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Run `just rust-lint` after modifying Rust code to ensure proper formatting, compilation, and linting (runs fmt + clippy strict)
Applied to files:
.github/workflows/mobile-build.yml
📚 Learning: 2025-12-08T19:55:33.330Z
Learnt from: CR
Repo: OpenSecretCloud/Maple PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-08T19:55:33.330Z
Learning: Applies to src-tauri/**/*.rs : Follow standard Rust conventions and rustfmt defaults for code formatting
Applied to files:
.github/workflows/mobile-build.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-linux
- GitHub Check: build-ios
- GitHub Check: build-android
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
.github/workflows/mobile-build.yml (2)
149-150:ORT_LIB_LOCATIONdevice-only is consistent with device CI—just ensure no simulator build is attempted.
If any step ever builds a simulator target, it’ll need a real simulator slice (or conditional env/config).
56-112: Remove redundant and ineffective.cargo/config.tomlgeneration—linking is already handled bybuild.rs.The workflow generates a
.cargo/config.tomlwith[target.aarch64-apple-ios.onnxruntime]sections, but this approach does not work. Cargo only parses these target-specific package tables when the named crate declareslinks = "onnxruntime"in its manifest. Theortcrate does not; it handles linking via its ownbuild.rsscript. The generated config sections are silently ignored by Cargo and have no effect.The actual linking is already correctly handled by
frontend/src-tauri/build.rs, which:
- Detects the target triple and selects the correct
xcframeworksubdirectory- Outputs proper
cargo:rustc-link-searchandcargo:rustc-link-libdirectives- Sets
ORT_LIB_LOCATIONenvironment variable for theortcrateDelete the "Configure Cargo for iOS ONNX Runtime" step and rely on the build script instead. If additional per-target overrides are later needed, they should be handled via
[target.<triple>]rustflagsor by modifying the build script logic, not via unused config sections.⛔ Skipped due to learnings
Learnt from: AnthonyRonning Repo: OpenSecretCloud/Maple PR: 372 File: frontend/src-tauri/Cargo.toml:9-9 Timestamp: 2026-01-08T17:09:40.432Z Learning: The OpenSecretCloud/Maple repository has comprehensive GitHub Actions workflows (e.g., desktop-build.yml) that automatically validate compilation and testing, so manual compilation verification reminders are unnecessary when reviewing version bumps or dependency updates..github/workflows/testflight-on-comment.yml (1)
219-229:xcrun altoolis still supported in Xcode 16.4 for TestFlight uploads—not removed.
altooldeprecation applies to macOS notarization only (usexcrun notarytoolfor that). For iOS IPA uploads to App Store Connect/TestFlight,xcrun altool --upload-appwith API key authentication (as shown) remains functional. Apple recommends alternatives like Transporter or App Store Connect API for new workflows, but the current code will not fail on Xcode 16.4 runners.frontend/src-tauri/scripts/build-ios-onnxruntime.sh (1)
109-120: Build flags for ONNX Runtime v1.22.2 are supported and documented.
The flags--use_xcode,--ios,--apple_sysroot,--osx_arch, and--cmake_extra_definesare all valid in v1.22.2. The iOS build approach in this script aligns with the official ONNX Runtime documentation. Note: ONNX Runtime v1.22.2 requires iOS SDK >= 15.1.
| check-comment: | ||
| if: github.event.issue.pull_request && contains(github.event.comment.body, 'testflight build') | ||
| # Only run on issue_comment events, not on push | ||
| if: github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, 'testflight build') |
There was a problem hiding this comment.
deploy-testflight likely won’t run on push due to needs: check-comment being skipped.
On push, check-comment won’t execute (Line 20-21). Jobs that needs a skipped job typically get skipped too, so the temporary push trigger (Line 6-11) may be a no-op.
Proposed fix (split push vs comment paths)
jobs:
check-comment:
# Only run on issue_comment events, not on push
if: github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, 'testflight build')
runs-on: ubuntu-latest
@@
deploy-testflight:
- needs: check-comment
- # Run on push to ios-tts branch OR when triggered by comment with approval
- if: github.event_name == 'push' || needs.check-comment.outputs.should-deploy == 'true'
+ # Run on push to ios-tts branch OR when triggered by comment with approval
+ if: github.event_name == 'push' || needs.check-comment.outputs.should-deploy == 'true'
+ needs: check-comment
runs-on: macos-latest-xlargeIf this still skips on push in practice, the robust pattern is:
- keep
deploy-testflightwithoutneeds - compute
PR_REF/PR_NUMBERin-step based on event type - gate comment-posting steps on
issue_comment
Also applies to: 72-75
🤖 Prompt for AI Agents
In @.github/workflows/testflight-on-comment.yml around lines 19 - 21, The
workflow currently makes the deploy-testflight job depend on the check-comment
job (job id check-comment), so when a push event skips check-comment the
deploy-testflight job will be skipped too; remove the needs: check-comment
dependency or split the workflow into two paths so deploy-testflight runs on
push independently and only the comment-related steps are gated by
check-comment; specifically, ensure deploy-testflight (the job named
deploy-testflight) does not require check-comment, compute PR_REF/PR_NUMBER
inside a step (detecting github.event_name == 'push' vs 'issue_comment'), and
conditionally run the comment-posting steps only when the event is issue_comment
(use the check-comment job or an if that references github.event_name and the
presence of the comment).
| - name: Configure Cargo for iOS ONNX Runtime | ||
| run: | | ||
| # Create cargo config with absolute paths for iOS builds | ||
| # This overrides ort-sys's build script to use our built-from-source library | ||
| WORKSPACE="${{ github.workspace }}" | ||
| mkdir -p "${WORKSPACE}/frontend/src-tauri/.cargo" | ||
| cat > "${WORKSPACE}/frontend/src-tauri/.cargo/config.toml" << EOF | ||
| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
| EOF |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find the workflow file and check all similar sections
fd -n "testflight-on-comment.yml" .
wc -l .github/workflows/testflight-on-comment.ymlRepository: OpenSecretCloud/Maple
Length of output: 360
🏁 Script executed:
# Verify whether any repo code parses the custom .cargo/config.toml tables
rg -n "target\.[a-zA-Z0-9_\-]+\.onnxruntime" --hidden
rg -n "rustc-link-search|rustc-link-lib" --hidden
rg -n "ORT_LIB_LOCATION" --hiddenRepository: OpenSecretCloud/Maple
Length of output: 3630
🏁 Script executed:
# Check for any build.rs files that might read cargo config
fd -n "build\.rs" .
# Check for references to .cargo/config or CARGO_HOME
rg -n "\.cargo/config|CARGO_HOME" --hidden -t toml -t rs -t yamlRepository: OpenSecretCloud/Maple
Length of output: 322
🏁 Script executed:
# Look at lines 216-218 in the workflow to see if similar code exists
sed -n '210,225p' .github/workflows/testflight-on-comment.ymlRepository: OpenSecretCloud/Maple
Length of output: 901
🏁 Script executed:
# Get the full build.rs file to understand the complete linking strategy
cat -n frontend/src-tauri/build.rsRepository: OpenSecretCloud/Maple
Length of output: 1647
🏁 Script executed:
# Check if there's any documentation about this setup
rg -n "cargo.*config|\.cargo.*config" --hidden -t mdRepository: OpenSecretCloud/Maple
Length of output: 47
🌐 Web query:
Cargo config.toml custom target subtables syntax support
💡 Result:
Short answer: Yes — Cargo's config.toml supports target-specific subtables of the form [target.] (and custom target-spec paths are normalized to a triple name), but the config's conditional [target.'cfg(...)'] form has limits (notably it does not observe crate-level --features when evaluated). References:
- Official Cargo config docs: target. keys (linker, runner, rustflags, rustdocflags, etc.). [1]
- cargo-config2 note: custom target-spec files are converted to a triple name so they work with target.. [2]
- Community discussion showing [target.'cfg(...)'] exists but that user-supplied features (cargo --features) are not available to config-level cfg predicates. [3]
If you want, tell me the exact triple or cfg expression you want to use and I’ll show the exact config.toml snippet.
Remove or replace the non-standard .cargo/config.toml generation—the custom [target.*.onnxruntime] tables are ignored by Cargo.
The generated config file uses non-standard Cargo syntax: custom subtables like [target.aarch64-apple-ios.onnxruntime] with rustc-link-search and rustc-link-lib keys are not recognized by Cargo. (Cargo's config.toml only accepts [target.<triple>] with linker, runner, rustflags, etc.) The actual linking is already handled correctly by build.rs, which emits the proper cargo:rustc-link-search and cargo:rustc-link-lib directives at lines 18–19, and the ORT_LIB_LOCATION environment variable at line 26 is read by the ort crate. The config generation is dead code that should be removed to avoid misleading future maintainers.
Note: The x86_64 simulator path is correct—build.rs line 11 intentionally treats x86_64 as a simulator target, consistent with the config at lines 172–174.
🤖 Prompt for AI Agents
In @.github/workflows/testflight-on-comment.yml around lines 154 - 175, Remove
the "Configure Cargo for iOS ONNX Runtime" step that generates a
.cargo/config.toml with non-standard `[target.*.onnxruntime]` tables; they are
ignored by Cargo. Instead, delete that generation block (or replace it with a
short explanatory comment) and rely on the existing build.rs logic that emits
the `cargo:rustc-link-search` / `cargo:rustc-link-lib` directives and the
ORT_LIB_LOCATION environment variable consumed by the ort crate to handle
linking.
| # SKIP SIMULATOR BUILD for now | ||
| # The simulator build has a bug where it tries to link against the wrong iconv library: | ||
| # "ld: building for 'iOS-simulator', but linking in dylib built for 'iOS'" | ||
| # For TestFlight/App Store deployment, we only need the device build anyway. | ||
| # Local development can use the desktop version or a physical device. | ||
| echo "" | ||
| echo "Skipping iOS simulator build (known ONNX Runtime CMake bug with libiconv)" | ||
| echo "Device build is sufficient for TestFlight deployment" | ||
| IOS_SIM_ARM64_LIB="" | ||
|
|
||
| # Create output directories | ||
| echo "" | ||
| echo "========================================" | ||
| echo "Creating xcframework..." | ||
| echo "========================================" | ||
|
|
||
| mkdir -p "${OUTPUT_DIR}" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64-simulator" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/Headers" | ||
|
|
||
| # Copy the device library | ||
| cp "$IOS_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64/libonnxruntime.a" | ||
|
|
||
| # Copy the simulator library (arm64 only for now) | ||
| if [ -n "$IOS_SIM_ARM64_LIB" ] && [ -f "$IOS_SIM_ARM64_LIB" ]; then | ||
| cp "$IOS_SIM_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64-simulator/libonnxruntime.a" | ||
| else | ||
| echo "Warning: No simulator library available" | ||
| fi |
There was a problem hiding this comment.
XCFramework is likely invalid: simulator slice is declared but no simulator library is copied.
You create ios-arm64-simulator and include it in Info.plist (Line 218-233), but you intentionally don’t build/copy a simulator libonnxruntime.a (Line 154-183). This will break any simulator build (and may break some tooling even for device-only workflows).
Proposed fix (device-only xcframework: omit simulator slice entirely)
- mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64-simulator"
mkdir -p "${XCFRAMEWORK_DIR}/Headers"
@@
- # Copy the simulator library (arm64 only for now)
- if [ -n "$IOS_SIM_ARM64_LIB" ] && [ -f "$IOS_SIM_ARM64_LIB" ]; then
- cp "$IOS_SIM_ARM64_LIB" "${XCFRAMEWORK_DIR}/ios-arm64-simulator/libonnxruntime.a"
- else
- echo "Warning: No simulator library available"
- fi
+ echo "No simulator library (device-only build)"
@@
- <dict>
- <key>HeadersPath</key>
- <string>Headers</string>
- <key>LibraryIdentifier</key>
- <string>ios-arm64-simulator</string>
- <key>LibraryPath</key>
- <string>libonnxruntime.a</string>
- <key>SupportedArchitectures</key>
- <array>
- <string>arm64</string>
- </array>
- <key>SupportedPlatform</key>
- <string>ios</string>
- <key>SupportedPlatformVariant</key>
- <string>simulator</string>
- </dict>Also applies to: 196-234
🤖 Prompt for AI Agents
In @frontend/src-tauri/scripts/build-ios-onnxruntime.sh around lines 154 - 183,
The XCFramework currently declares a simulator slice but never provides a
simulator library, causing an invalid xcframework; change the script to produce
a device-only XCFramework by removing creation/usage of the ios-arm64-simulator
slice and related Info.plist entries when IOS_SIM_ARM64_LIB is empty: stop
creating the "${XCFRAMEWORK_DIR}/ios-arm64-simulator" directory, skip copying or
referencing the simulator lib when IOS_SIM_ARM64_LIB is unset, and ensure the
generated Info.plist (the block that mentions ios-arm64-simulator) only includes
the ios-arm64 slice or is conditionally built when IOS_SIM_ARM64_LIB exists;
alternatively, keep the existing conditional copy but also conditionally build
the Info.plist and directory based on IOS_SIM_ARM64_LIB so the simulator slice
is never declared unless a valid simulator lib is present.
left a comment
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds Text-to-Speech support for iOS by building ONNX Runtime 1.22.2 from source and integrating it with the existing Supertonic TTS implementation. The changes enable on-device TTS for iPhones and iPads.
Major Changes:
- Added CI/CD pipeline to build ONNX Runtime from source with caching (90min build cached for reuse)
- Extended Rust TTS module to support iOS alongside desktop platforms
- Updated frontend to detect and enable TTS on iOS devices
- Added iOS-specific path handling for model storage (
~/Documents/tts_models)
Critical Issues Found:
- Cargo config syntax errors: Invalid
[target.<triple>.onnxruntime]sections in both workflows will be ignored by Cargo, potentially causing linking failures - Directory name mismatches:
build.rsexpectsios-arm64_x86_64-simulatorbut build script createsios-arm64-simulator, causing simulator builds to fail - Workflow logic bug: PR comment steps in
testflight-on-comment.ymlwill fail when triggered by push events (missing pr-number) - Unused script:
setup-ios-onnxruntime.shdownloads pre-built binaries but is never used
Positive Aspects:
- Rust code changes are clean and follow existing patterns
- Proper platform-specific conditionals throughout
- Good error handling in model download/loading
- Appropriate dependency configuration (disabled rayon, download-binaries for iOS)
Confidence Score: 2/5
- This PR has multiple critical bugs that will cause build and deployment failures
- Score of 2 reflects critical issues in CI/CD configuration: invalid Cargo config syntax will prevent proper linking, directory name mismatches will break simulator builds, and workflow logic errors will cause PR comment failures. These are not edge cases but fundamental bugs that will manifest on every build attempt. The Rust implementation itself is solid (would be 4-5 alone), but the build infrastructure has severe issues.
- Critical attention needed for
.github/workflows/mobile-build.yml,.github/workflows/testflight-on-comment.yml, andfrontend/src-tauri/build.rs- all three have bugs that will cause build failures
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 2/5 | Added ONNX Runtime iOS build pipeline with caching, but has critical Cargo config syntax errors and directory name mismatches that will cause build failures |
| .github/workflows/testflight-on-comment.yml | 2/5 | Added ONNX Runtime build steps and push trigger for testing, but has same Cargo config errors as mobile-build.yml plus PR comment failures when triggered by push |
| frontend/src-tauri/Cargo.toml | 4/5 | Added iOS-specific TTS dependencies with correct feature flags (disabled rayon, download-binaries, copy-dylibs). Clean addition mirroring desktop deps. |
| frontend/src-tauri/build.rs | 2/5 | Added iOS ONNX Runtime linking configuration, but simulator directory name (ios-arm64_x86_64-simulator) doesn't match what build script creates (ios-arm64-simulator) |
| frontend/src-tauri/src/lib.rs | 5/5 | Added iOS TTS support by extending platform conditionals and adding TTS commands to iOS invoke handler. Clean integration following existing patterns. |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 4/5 | Comprehensive script to build ONNX Runtime 1.22.2 from source with retry logic and proper error handling. Skips simulator build due to known CMake bug. |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Build as build-ios-onnxruntime.sh
participant Cache as Cache Storage
participant Cargo as Cargo Build
participant Xcode as Xcode Build
participant TF as TestFlight
Note over GHA,TF: iOS TTS Build & Deploy Flow
GHA->>Cache: Check ONNX Runtime cache
alt Cache miss
GHA->>Build: Execute build script
Build->>Build: Clone ONNX Runtime 1.22.2
Build->>Build: Build for iOS arm64
Build->>Build: Combine static libraries
Build->>Build: Create xcframework structure
Build->>GHA: Return xcframework
GHA->>Cache: Store in cache
else Cache hit
Cache->>GHA: Restore xcframework
end
GHA->>GHA: Generate Cargo config.toml
Note over GHA: Sets rustc-link-search paths
GHA->>Cargo: Build Rust library
Cargo->>Cargo: Link ONNX Runtime static lib
Cargo->>Cargo: Compile TTS module (iOS enabled)
Cargo->>Xcode: Provide static library
GHA->>Xcode: Build iOS app
Xcode->>Xcode: Link Rust + ONNX Runtime
Xcode->>Xcode: Create IPA package
Xcode->>GHA: Return IPA
alt Deploy condition met
GHA->>TF: Upload IPA via altool
TF->>TF: Process for TestFlight
end
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) |
There was a problem hiding this comment.
Directory name mismatch: build-ios-onnxruntime.sh creates ios-arm64-simulator but build.rs expects ios-arm64_x86_64-simulator.
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 12:12
Comment:
Directory name mismatch: `build-ios-onnxruntime.sh` creates `ios-arm64-simulator` but `build.rs` expects `ios-arm64_x86_64-simulator`.
```suggestion
format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir)
```
How can I resolve this? If you propose a fix, please make it concise.| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] |
There was a problem hiding this comment.
Invalid Cargo config syntax: [target.aarch64-apple-ios.onnxruntime] is not a standard Cargo config section. Cargo only supports [target.<triple>] sections with keys like rustc-link-search and rustc-link-lib. The .onnxruntime suffix will be ignored by Cargo.
Remove .onnxruntime from all three target sections (lines 97, 101, 105).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 97:97
Comment:
Invalid Cargo config syntax: `[target.aarch64-apple-ios.onnxruntime]` is not a standard Cargo config section. Cargo only supports `[target.<triple>]` sections with keys like `rustc-link-search` and `rustc-link-lib`. The `.onnxruntime` suffix will be ignored by Cargo.
Remove `.onnxruntime` from all three target sections (lines 97, 101, 105).
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Directory name mismatch: build-ios-onnxruntime.sh creates ios-arm64-simulator but workflow references ios-arm64-simulator.
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 102:102
Comment:
Directory name mismatch: `build-ios-onnxruntime.sh` creates `ios-arm64-simulator` but workflow references `ios-arm64-simulator`.
```suggestion
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
```
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Same directory mismatch as line 102 - should be ios-arm64-simulator not ios-arm64-simulator.
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 106:106
Comment:
Same directory mismatch as line 102 - should be `ios-arm64-simulator` not `ios-arm64-simulator`.
```suggestion
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
```
How can I resolve this? If you propose a fix, please make it concise.| # Auto-generated cargo config for iOS ONNX Runtime linking | ||
| # Uses absolute paths because xcodebuild may run cargo from different directories | ||
|
|
||
| [target.aarch64-apple-ios.onnxruntime] |
There was a problem hiding this comment.
Same invalid Cargo config syntax as mobile-build.yml - remove .onnxruntime suffix.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 164:164
Comment:
Same invalid Cargo config syntax as mobile-build.yml - remove `.onnxruntime` suffix.
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Directory mismatch - should be ios-arm64-simulator.
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 169:169
Comment:
Directory mismatch - should be `ios-arm64-simulator`.
```suggestion
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
```
How can I resolve this? If you propose a fix, please make it concise.| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Directory mismatch - should be ios-arm64-simulator.
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 173:173
Comment:
Directory mismatch - should be `ios-arm64-simulator`.
```suggestion
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
```
How can I resolve this? If you propose a fix, please make it concise.
commented
Jan 9, 2026
Additional Comments (3)
Add condition: Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 230:239
Comment:
When workflow runs via push trigger (not comment), `needs.check-comment.outputs.pr-number` will be empty/undefined, causing this step to fail or create an invalid comment.
Add condition: `if: success() && github.event_name == 'issue_comment'`
How can I resolve this? If you propose a fix, please make it concise.
Add condition: Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 242:252
Comment:
Same issue as success case - `pr-number` will be undefined when running via push trigger.
Add condition: `if: failure() && github.event_name == 'issue_comment'`
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 1:79
Comment:
This script is never referenced in the workflows or build process. The workflows use `build-ios-onnxruntime.sh` instead. Consider removing this dead code or documenting when/why it should be used.
How can I resolve this? If you propose a fix, please make it concise. |
iOS WKWebView requires explicit audioContext.resume() call even when created during a user gesture, as the context may start in suspended state. This is a no-op on macOS/Linux where the context is already running. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
left a comment
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
This PR adds iOS TTS support using ONNX Runtime. The core implementation is solid—the Rust TTS code, iOS-specific path handling, and frontend integration are well-designed. However, there are critical build configuration issues that will prevent successful compilation:
Critical Issues Found
1. Invalid Cargo Config Syntax (Both Workflows)
The generated .cargo/config.toml uses invalid section names like [target.aarch64-apple-ios.onnxruntime]. Standard Cargo only recognizes [target.<triple>] without custom suffixes. The .onnxruntime suffix will be silently ignored, causing linker flags to not be applied.
2. Directory Name Mismatch
There's a critical inconsistency in simulator directory naming:
- build-ios-onnxruntime.sh creates:
ios-arm64-simulator - setup-ios-onnxruntime.sh creates:
ios-arm64_x86_64-simulator - build.rs expects:
ios-arm64_x86_64-simulator - Workflows reference:
ios-arm64-simulator
This mismatch means builds will fail with "library not found" errors when the cache misses and the build script runs.
3. Missing Conditionals in testflight-on-comment.yml
The PR comment steps (lines 230-252) will fail when the workflow runs via the push trigger because pr-number will be undefined.
What Works Well
- iOS TTS module integration with proper conditional compilation
- iOS-specific model storage path using Documents directory
- Frontend AudioContext.resume() for iOS compatibility
- Dependency configuration in Cargo.toml
- Build script retry logic and error handling
Recommendation
These configuration issues must be fixed before merge—they will cause 100% build failure rate when building from source (cache miss).
Confidence Score: 0/5
- This PR has critical build configuration bugs that will cause guaranteed build failures
- Score reflects three critical issues that will prevent successful builds: (1) Invalid Cargo config syntax that will be silently ignored causing linker failures, (2) Directory path mismatches between build script output and expected locations, (3) Missing conditionals causing workflow failures. While the core TTS implementation code is solid, the build infrastructure has fundamental issues that must be fixed before this can work.
- Critical attention needed: .github/workflows/mobile-build.yml, .github/workflows/testflight-on-comment.yml, frontend/src-tauri/build.rs, and frontend/src-tauri/scripts/build-ios-onnxruntime.sh must be fixed to resolve path mismatches and invalid Cargo config syntax
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 1/5 | Critical issues: Invalid Cargo config syntax (.onnxruntime suffix) and simulator path mismatch (ios-arm64-simulator vs ios-arm64_x86_64-simulator) will cause build failures |
| .github/workflows/testflight-on-comment.yml | 1/5 | Critical issues: Invalid Cargo config syntax, path mismatch with build script, and missing conditionals for PR comment steps when triggered via push |
| frontend/src-tauri/build.rs | 1/5 | Critical path mismatch: expects ios-arm64_x86_64-simulator but build script creates ios-arm64-simulator, will cause linker failures |
| frontend/src-tauri/scripts/build-ios-onnxruntime.sh | 2/5 | Creates ios-arm64-simulator directory but other files expect ios-arm64_x86_64-simulator, causing path inconsistency |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant BuildScript as build-ios-onnxruntime.sh
participant Cache as Actions Cache
participant CargoConfig as .cargo/config.toml
participant BuildRS as build.rs
participant Cargo as Cargo Build
participant XCode as Xcode Build
GHA->>Cache: Check for onnxruntime-ios cache
alt Cache Hit
Cache-->>GHA: Restore cached xcframework
else Cache Miss
GHA->>BuildScript: Execute build script
BuildScript->>BuildScript: Clone ONNX Runtime repo
BuildScript->>BuildScript: Build for ios-arm64
BuildScript->>BuildScript: Create xcframework/ios-arm64-simulator/
BuildScript-->>GHA: Built xcframework
end
GHA->>CargoConfig: Generate .cargo/config.toml
Note over CargoConfig: ❌ Invalid syntax: [target.*.onnxruntime]
Note over CargoConfig: ❌ Path: ios-arm64-simulator
GHA->>Cargo: Start iOS build
Cargo->>BuildRS: Execute build.rs
BuildRS->>BuildRS: Check target (simulator/device)
Note over BuildRS: ❌ Expects: ios-arm64_x86_64-simulator
Note over BuildRS: ⚠️ Gets: ios-arm64-simulator
BuildRS->>Cargo: Set linker paths
Cargo->>XCode: Compile Rust for iOS
XCode-->>Cargo: ❌ Linker Error: libonnxruntime.a not found
Cargo-->>GHA: ❌ Build Failed
| // Check if building for simulator or device | ||
| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) |
There was a problem hiding this comment.
Critical path mismatch: This code expects ios-arm64_x86_64-simulator but the build script (build-ios-onnxruntime.sh) creates ios-arm64-simulator (line 172). The setup script downloads to ios-arm64_x86_64-simulator which matches this code, but the build script uses a different directory name.
This will cause linker failures when building from source (cache miss) because the library won't be found at the expected path.
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | |
| format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 12:12
Comment:
Critical path mismatch: This code expects `ios-arm64_x86_64-simulator` but the build script (`build-ios-onnxruntime.sh`) creates `ios-arm64-simulator` (line 172). The setup script downloads to `ios-arm64_x86_64-simulator` which matches this code, but the build script uses a different directory name.
This will cause linker failures when building from source (cache miss) because the library won't be found at the expected path.
```suggestion
format!("{}/onnxruntime.xcframework/ios-arm64-simulator", ort_dir)
```
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Invalid Cargo config format: The custom section suffix .onnxruntime (e.g., [target.aarch64-apple-ios.onnxruntime]) is not valid in Cargo's config format. Standard Cargo only recognizes [target.<triple>] sections with keys like rustc-link-search and rustc-link-lib.
The .onnxruntime suffix will be silently ignored by Cargo, meaning these linker flags won't be applied, causing build failures.
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 97:107
Comment:
Invalid Cargo config format: The custom section suffix `.onnxruntime` (e.g., `[target.aarch64-apple-ios.onnxruntime]`) is not valid in Cargo's config format. Standard Cargo only recognizes `[target.<triple>]` sections with keys like `rustc-link-search` and `rustc-link-lib`.
The `.onnxruntime` suffix will be silently ignored by Cargo, meaning these linker flags won't be applied, causing build failures.
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Path mismatch with build script output: These paths reference ios-arm64-simulator, but the build-ios-onnxruntime.sh script creates this directory (line 172), while setup-ios-onnxruntime.sh creates ios-arm64_x86_64-simulator. The build.rs file expects ios-arm64_x86_64-simulator (line 12).
There's an inconsistency:
- setup script →
ios-arm64_x86_64-simulator - build script →
ios-arm64-simulator - build.rs →
ios-arm64_x86_64-simulator - workflows →
ios-arm64-simulator
This will cause build failures depending on which path is used (download vs build from source).
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 101:106
Comment:
Path mismatch with build script output: These paths reference `ios-arm64-simulator`, but the `build-ios-onnxruntime.sh` script creates this directory (line 172), while `setup-ios-onnxruntime.sh` creates `ios-arm64_x86_64-simulator`. The build.rs file expects `ios-arm64_x86_64-simulator` (line 12).
There's an inconsistency:
- setup script → `ios-arm64_x86_64-simulator`
- build script → `ios-arm64-simulator`
- build.rs → `ios-arm64_x86_64-simulator`
- workflows → `ios-arm64-simulator`
This will cause build failures depending on which path is used (download vs build from source).
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Invalid Cargo config format: Same issue as mobile-build.yml - the .onnxruntime suffix in section names like [target.aarch64-apple-ios.onnxruntime] is not valid Cargo syntax and will be ignored.
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 164:174
Comment:
Invalid Cargo config format: Same issue as mobile-build.yml - the `.onnxruntime` suffix in section names like `[target.aarch64-apple-ios.onnxruntime]` is not valid Cargo syntax and will be ignored.
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] |
There was a problem hiding this comment.
Path mismatch with build script: Same directory name inconsistency as in mobile-build.yml. The workflows reference ios-arm64-simulator but build.rs expects ios-arm64_x86_64-simulator.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 168:173
Comment:
Path mismatch with build script: Same directory name inconsistency as in mobile-build.yml. The workflows reference `ios-arm64-simulator` but build.rs expects `ios-arm64_x86_64-simulator`.
How can I resolve this? If you propose a fix, please make it concise.
commented
Jan 9, 2026
Additional Comments (2)
The step should only run when triggered by a comment: Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 230:240
Comment:
Missing conditional check: When this workflow runs via the `push` trigger (line 10-11), `needs.check-comment.outputs.pr-number` will be undefined/empty, causing this GitHub API call to fail or post to an invalid issue number.
The step should only run when triggered by a comment:
```suggestion
- name: Comment on PR with success
if: success() && github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ needs.check-comment.outputs.pr-number }},
body: '✅ TestFlight deployment completed successfully!'
});
```
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 242:252
Comment:
Missing conditional check: Same issue as the success comment - when running via push trigger, `pr-number` will be undefined.
```suggestion
- name: Comment on PR with failure
if: failure() && github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ needs.check-comment.outputs.pr-number }},
body: '❌ TestFlight deployment failed. Check the [workflow logs](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '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/actions/runs/' + context.runId + ') for details.'
});
```
How can I resolve this? If you propose a fix, please make it concise. |
The old TTS implementation (PR #235) had UIBackgroundModes with audio capability which was later removed. iOS requires this capability to play audio properly in WKWebView. Also added debug logging and error notifications for TTS playback to help diagnose issues. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
left a comment
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
Adds iOS TTS support using ONNX Runtime 1.22.2 built from source, enabling the Supertonic model to run on-device. Introduces GitHub Actions steps to build and cache the xcframework (~90min first build), then links it statically into the iOS app. The frontend enables TTS for iOS with explicit AudioContext.resume() to handle iOS audio restrictions.
Confidence Score: 2/5
- Moderate risk due to workflow logic errors that will cause failures when triggered via push events
- The testflight-on-comment workflow has logic errors in PR comment steps that reference undefined outputs when triggered via push (lines 230-252), causing runtime failures. Additionally, both workflows generate invalid Cargo config with
.onnxruntimesuffixes that Cargo ignores. There's also a potential path mismatch between build.rs expectingios-arm64_x86_64-simulatorwhile build-ios-onnxruntime.sh createsios-arm64-simulator. - .github/workflows/testflight-on-comment.yml (PR comment steps will fail on push trigger), frontend/src-tauri/build.rs (simulator directory path mismatch)
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| .github/workflows/mobile-build.yml | 2/5 | Adds ONNX Runtime iOS build with caching; cargo config uses invalid .onnxruntime suffix which Cargo ignores |
| .github/workflows/testflight-on-comment.yml | 2/5 | Adds TestFlight deployment with ONNX Runtime support; PR comment steps will fail when triggered via push event |
| frontend/src-tauri/build.rs | 3/5 | Adds iOS-specific ONNX Runtime linking configuration; correctly handles device vs simulator paths |
Sequence Diagram
sequenceDiagram
participant GHA as GitHub Actions
participant Cache as Cache Storage
participant Build as ONNX Build Script
participant Cargo as Cargo/Tauri
participant iOS as iOS App
participant TTS as TTS Engine
GHA->>Cache: Check for onnxruntime-ios cache
alt Cache Hit
Cache-->>GHA: Return cached xcframework
else Cache Miss
GHA->>Build: Run build-ios-onnxruntime.sh
Build->>Build: Clone ONNX Runtime 1.22.2
Build->>Build: Build for iOS arm64 (90 min)
Build->>Build: Combine static libraries
Build-->>GHA: Create xcframework
GHA->>Cache: Store xcframework
end
GHA->>GHA: Generate .cargo/config.toml
GHA->>Cargo: Set ORT_LIB_LOCATION env var
Cargo->>Cargo: build.rs links xcframework
Cargo->>iOS: Build iOS app with TTS
iOS->>TTS: User requests TTS
TTS->>TTS: Download models (~264MB)
TTS->>TTS: Load ONNX sessions
TTS->>TTS: Synthesize audio
TTS-->>iOS: Return base64 WAV
iOS->>iOS: AudioContext.resume() for iOS
iOS->>iOS: Play audio
| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Cargo config sections use invalid custom suffix .onnxruntime which Cargo ignores. The standard format is [target.<triple>] with keys like rustc-link-search and rustc-link-lib. This configuration won't affect the build—the actual linking is handled by build.rs (line 18-19) and the ORT_LIB_LOCATION environment variable (line 150). Consider removing these non-functional config sections or restructuring them to valid Cargo target configuration if they're intended to override ort-sys behavior.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 97:107
Comment:
Cargo config sections use invalid custom suffix `.onnxruntime` which Cargo ignores. The standard format is `[target.<triple>]` with keys like `rustc-link-search` and `rustc-link-lib`. This configuration won't affect the build—the actual linking is handled by `build.rs` (line 18-19) and the `ORT_LIB_LOCATION` environment variable (line 150). Consider removing these non-functional config sections or restructuring them to valid Cargo target configuration if they're intended to override ort-sys behavior.
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Same issue as mobile-build.yml—these cargo config sections with .onnxruntime suffix are non-standard and will be ignored by Cargo.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 164:174
Comment:
Same issue as mobile-build.yml—these cargo config sections with `.onnxruntime` suffix are non-standard and will be ignored by Cargo.
How can I resolve this? If you propose a fix, please make it concise.| let target = std::env::var("TARGET").unwrap_or_default(); | ||
| let lib_path = if target.contains("sim") || target.contains("x86_64") { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64_x86_64-simulator", ort_dir) | ||
| } else { | ||
| format!("{}/onnxruntime.xcframework/ios-arm64", ort_dir) | ||
| }; |
There was a problem hiding this comment.
Path logic checks for "sim" or "x86_64" but maps to ios-arm64_x86_64-simulator directory. However, the build script creates ios-arm64-simulator directory (build-ios-onnxruntime.sh:172), causing a mismatch. The setup script (setup-ios-onnxruntime.sh:49) creates ios-arm64_x86_64-simulator matching this code, but the build script differs. Which directory structure is correct—build script creates ios-arm64-simulator while this expects ios-arm64_x86_64-simulator?
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/build.rs
Line: 10:15
Comment:
Path logic checks for "sim" or "x86_64" but maps to `ios-arm64_x86_64-simulator` directory. However, the build script creates `ios-arm64-simulator` directory (build-ios-onnxruntime.sh:172), causing a mismatch. The setup script (setup-ios-onnxruntime.sh:49) creates `ios-arm64_x86_64-simulator` matching this code, but the build script differs. Which directory structure is correct—build script creates ios-arm64-simulator while this expects ios-arm64_x86_64-simulator?
How can I resolve this? If you propose a fix, please make it concise.
left a comment
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @frontend/src/components/UnifiedChat.tsx:
- Around line 212-227: The ref update for prevPlaybackError.current is currently
unconditional and can swallow errors; modify the useEffect that watches
lastPlaybackError/currentPlayingId/messageId so that prevPlaybackError.current
is updated only when you actually call showNotification (i.e., move the
assignment inside the if block that checks lastPlaybackError !==
prevPlaybackError.current && currentPlayingId === messageId) so
non-playing-message errors do not override the ref and later identical errors on
the playing message will still trigger the notification; ensure you still
reference showNotification, lastPlaybackError, currentPlayingId and messageId in
the dependency array.
🧹 Nitpick comments (2)
frontend/src/services/tts/TTSContext.tsx (2)
228-287: Consider clearing playback error on successful completion.The
lastPlaybackErrorstate is cleared when starting new playback (line 226) but not when playback completes successfully. This could cause stale errors to be displayed if a component remounts after an error.♻️ Recommended enhancement
Clear the error in the
onendedhandler:source.onended = () => { console.log("[TTS] Playback ended"); if (sourceNodeRef.current !== source) { return; } setIsPlaying(false); setCurrentPlayingId(null); + setLastPlaybackError(null); if (audioUrlRef.current === audioUrl) { URL.revokeObjectURL(audioUrlRef.current); audioUrlRef.current = null; } void audioContext.close().catch(() => { // Ignore }); audioContextRef.current = null; sourceNodeRef.current = null; };
228-287: Consider refining debug logging for production.Extensive console logging has been added throughout the TTS playback flow, which is helpful for debugging iOS issues. For production, consider using a conditional logging framework or making these logs removable in production builds.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/src-tauri/gen/apple/maple_iOS/Info.plistis excluded by!**/gen/**
📒 Files selected for processing (2)
frontend/src/components/UnifiedChat.tsxfrontend/src/services/tts/TTSContext.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use path aliases (@/*maps to./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid usinganytype
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Runjust format,just lint, andjust buildafter making TypeScript/React changes to ensure code quality and compilation
Files:
frontend/src/services/tts/TTSContext.tsxfrontend/src/components/UnifiedChat.tsx
🧬 Code graph analysis (1)
frontend/src/components/UnifiedChat.tsx (2)
frontend/src/services/tts/TTSContext.tsx (1)
useTTS(347-353)frontend/src/contexts/NotificationContext.tsx (1)
useNotification(35-41)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-ios
- GitHub Check: build-android
- GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
frontend/src/services/tts/TTSContext.tsx (2)
244-247: LGTM: iOS AudioContext fix is correct.The explicit
await audioContext.resume()is necessary for iOS, where the AudioContext may start in a suspended state even after a user gesture. This is a known iOS Web Audio API issue, and callingresume()is safe on all platforms (no-op if already running).
64-65: The platform detection logic is correct and not redundant.isTauriDesktop()returnstrueonly for desktop platforms (macOS, Windows, Linux), explicitly excluding mobile. The additional(isTauri() && isIOS())check is necessary to include iOS support in the TTS environment detection.
| // Show notification when playback error occurs for this message | ||
| useEffect(() => { | ||
| if ( | ||
| lastPlaybackError && | ||
| lastPlaybackError !== prevPlaybackError.current && | ||
| currentPlayingId === messageId | ||
| ) { | ||
| showNotification({ | ||
| type: "error", | ||
| title: "TTS Playback Failed", | ||
| message: lastPlaybackError, | ||
| duration: 8000 | ||
| }); | ||
| } | ||
| prevPlaybackError.current = lastPlaybackError; | ||
| }, [lastPlaybackError, currentPlayingId, messageId, showNotification]); |
There was a problem hiding this comment.
Fix the error notification logic to prevent swallowed errors.
The prevPlaybackError.current is updated unconditionally outside the notification condition. This can cause errors to be silently dropped:
- If an error occurs for a non-playing message, the ref updates but no notification shows
- If the same error then occurs for the currently playing message, it won't show (not considered "new")
🐛 Proposed fix
Move the ref update inside the conditional block:
// Show notification when playback error occurs for this message
useEffect(() => {
if (
lastPlaybackError &&
lastPlaybackError !== prevPlaybackError.current &&
currentPlayingId === messageId
) {
showNotification({
type: "error",
title: "TTS Playback Failed",
message: lastPlaybackError,
duration: 8000
});
+ prevPlaybackError.current = lastPlaybackError;
}
- prevPlaybackError.current = lastPlaybackError;
}, [lastPlaybackError, currentPlayingId, messageId, showNotification]);🤖 Prompt for AI Agents
In @frontend/src/components/UnifiedChat.tsx around lines 212 - 227, The ref
update for prevPlaybackError.current is currently unconditional and can swallow
errors; modify the useEffect that watches
lastPlaybackError/currentPlayingId/messageId so that prevPlaybackError.current
is updated only when you actually call showNotification (i.e., move the
assignment inside the if block that checks lastPlaybackError !==
prevPlaybackError.current && currentPlayingId === messageId) so
non-playing-message errors do not override the ref and later identical errors on
the playing message will still trigger the notification; ensure you still
reference showNotification, lastPlaybackError, currentPlayingId and messageId in
the dependency array.
commented
Jan 9, 2026
Additional Comments (2)
Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 230:240
Comment:
When workflow runs via `push` trigger (lines 9-11), `needs.check-comment.outputs.pr-number` will be undefined, causing this API call to fail or post to an invalid issue. The step should only run for comment-triggered events.
```suggestion
- name: Comment on PR with success
if: success() && github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ needs.check-comment.outputs.pr-number }},
body: '✅ TestFlight deployment completed successfully!'
});
```
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 242:252
Comment:
Same issue as the success comment step—`pr-number` will be undefined when triggered via push event, causing this step to fail.
```suggestion
- name: Comment on PR with failure
if: failure() && github.event_name == 'issue_comment'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ needs.check-comment.outputs.pr-number }},
body: '❌ TestFlight deployment failed. Check the [workflow logs](https://github.com/' + context.repo.owner + '/' + context.repo.repo + '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/actions/runs/' + context.runId + ') for details.'
});
```
How can I resolve this? If you propose a fix, please make it concise. |
The old TTS implementation (PR #235) that worked on iOS used HTMLAudioElement (new Audio()), not Web Audio API. Switching back to this approach as Web Audio API has known issues with iOS WKWebView. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
left a comment
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @frontend/src/services/tts/TTSContext.tsx:
- Around line 168-171: stop() clears audioElementRef.current but doesn't detach
the old audio element's event handlers, so an old element's onended/onerror can
later run and set audioElementRef.current = null, breaking new playback; update
stop() to first capture the current element into a local variable (e.g., const
old = audioElementRef.current), if old exists remove its handlers (old.onended =
null; old.onerror = null), call old.pause(), then set audioElementRef.current =
null; mirror this same detach pattern used in the cleanup effect and ensure
speak() continues to set handlers only on the newly created element.
🧹 Nitpick comments (1)
frontend/src/services/tts/TTSContext.tsx (1)
217-217: Consider reducing console logging in production.The playback lifecycle has extensive console logging (~8 statements). While helpful for debugging this new iOS TTS feature, consider reducing verbosity or making logs conditional for production builds.
Also applies to: 221-221, 225-225, 235-235, 247-247, 258-260, 263-263
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
frontend/src/services/tts/TTSContext.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use path aliases (@/*maps to./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid usinganytype
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Runjust format,just lint, andjust buildafter making TypeScript/React changes to ensure code quality and compilation
Files:
frontend/src/services/tts/TTSContext.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: build-ios
- GitHub Check: build-linux
- GitHub Check: build-macos (universal-apple-darwin)
- GitHub Check: build-android
- GitHub Check: Cloudflare Pages
🔇 Additional comments (4)
frontend/src/services/tts/TTSContext.tsx (4)
64-65: LGTM!The platform detection logic correctly enables TTS on both desktop and iOS platforms, aligning with the PR objectives.
229-233: LGTM!Switching to
HTMLAudioElementis the correct approach for iOS WKWebView compatibility. The comment clearly documents the rationale and references the prior implementation.
52-52: LGTM!The
lastPlaybackErrorstate is properly typed, follows naming conventions, and is correctly integrated into the context.Also applies to: 75-75, 299-299
10-10: All platform utilities (isTauriDesktop,isIOS,isTauri) are properly exported from@/utils/platform.
| if (audioElementRef.current) { | ||
| audioElementRef.current.pause(); | ||
| audioElementRef.current = null; | ||
| } |
There was a problem hiding this comment.
Critical: Event handlers from previous playback can interfere with new playback.
When stop() is called, it clears audioElementRef.current but doesn't remove the onended and onerror handlers from the old audio element. If speak() is called again immediately:
stop()clears the ref- A new audio element is created and ref is set to the new element (line 232)
- The old audio element's
onendedhandler may fire (lines 234-243) - The handler unconditionally sets
audioElementRef.current = null(line 242), breaking the new playback
🔒 Recommended fix: Clear event handlers in stop()
const stop = useCallback(() => {
if (audioElementRef.current) {
audioElementRef.current.pause();
+ audioElementRef.current.onended = null;
+ audioElementRef.current.onerror = null;
audioElementRef.current = null;
}
if (audioUrlRef.current) {
URL.revokeObjectURL(audioUrlRef.current);
audioUrlRef.current = null;
}
setIsPlaying(false);
setCurrentPlayingId(null);
}, []);Apply the same pattern in the cleanup effect:
return () => {
if (unlistenRef.current) {
unlistenRef.current();
}
if (audioElementRef.current) {
audioElementRef.current.pause();
+ audioElementRef.current.onended = null;
+ audioElementRef.current.onerror = null;
audioElementRef.current = null;
}
if (audioUrlRef.current) {
URL.revokeObjectURL(audioUrlRef.current);
audioUrlRef.current = null;
}
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (audioElementRef.current) { | |
| audioElementRef.current.pause(); | |
| audioElementRef.current = null; | |
| } | |
| if (audioElementRef.current) { | |
| audioElementRef.current.pause(); | |
| audioElementRef.current.onended = null; | |
| audioElementRef.current.onerror = null; | |
| audioElementRef.current = null; | |
| } |
🤖 Prompt for AI Agents
In @frontend/src/services/tts/TTSContext.tsx around lines 168 - 171, stop()
clears audioElementRef.current but doesn't detach the old audio element's event
handlers, so an old element's onended/onerror can later run and set
audioElementRef.current = null, breaking new playback; update stop() to first
capture the current element into a local variable (e.g., const old =
audioElementRef.current), if old exists remove its handlers (old.onended = null;
old.onerror = null), call old.pause(), then set audioElementRef.current = null;
mirror this same detach pattern used in the cleanup effect and ensure speak()
continues to set handlers only on the newly created element.
commented
Jan 9, 2026
Greptile OverviewGreptile SummaryThis PR adds iOS TTS support using ONNX Runtime 1.22.2, building on the existing desktop TTS implementation. The changes enable on-device text-to-speech for iOS using the Supertonic model. Key Changes
Critical Issues Found1. Directory Name Mismatch (P0 - Build Blocker)The build script creates
2. Invalid Cargo Configuration (P0 - Build Blocker)Both workflows generate Cargo config with invalid syntax:
3. Version Mismatch (P1 - Consistency Issue)
Positive Aspects
Confidence Score: 1/5
Important Files ChangedFile Analysis
Sequence DiagramsequenceDiagram
participant User
participant TTSContext
participant TauriBackend
participant ONNX
participant iOS
Note over User,iOS: TTS Initialization Flow
User->>TTSContext: App starts on iOS
TTSContext->>TauriBackend: checkStatus()
TauriBackend->>iOS: Check ~/Documents/tts_models
iOS-->>TauriBackend: Models not found
TauriBackend-->>TTSContext: status: not_downloaded
User->>TTSContext: Click download TTS models
TTSContext->>TauriBackend: startDownload()
TauriBackend->>TauriBackend: Download from HuggingFace
Note over TauriBackend: Downloads 264MB models
TauriBackend-->>TTSContext: Progress events
TauriBackend->>iOS: Save to ~/Documents/tts_models
TauriBackend->>TauriBackend: tts_load_models()
TauriBackend->>ONNX: Load ONNX models
ONNX-->>TauriBackend: Models loaded
TauriBackend-->>TTSContext: status: ready
Note over User,iOS: TTS Synthesis Flow
User->>TTSContext: Click speak button
TTSContext->>TTSContext: Preprocess text (remove code blocks)
TTSContext->>TauriBackend: tts_synthesize(text)
TauriBackend->>ONNX: Run inference
Note over ONNX: duration_predictor → text_encoder<br/>→ vector_estimator → vocoder
ONNX-->>TauriBackend: Audio waveform
TauriBackend-->>TTSContext: Base64 WAV audio
TTSContext->>TTSContext: Create Audio element
TTSContext->>iOS: Play audio via HTMLAudioElement
iOS-->>User: Audio playback
|
|
|
||
| mkdir -p "${OUTPUT_DIR}" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64" | ||
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64-simulator" |
There was a problem hiding this comment.
Directory name mismatch causing build failure: This script creates ios-arm64-simulator but other components expect ios-arm64_x86_64-simulator.
Impact: When the build script is used (on cache miss), it creates a directory structure incompatible with:
build.rsline 12 which looks forios-arm64_x86_64-simulatorsetup-ios-onnxruntime.shwhich createsios-arm64_x86_64-simulator- The GitHub Actions workflows which reference
ios-arm64-simulatorin the generated cargo config
This will cause linker errors when building for iOS simulator.
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64-simulator" | |
| mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator" |
Also update line 180, 222, and 256 to use ios-arm64_x86_64-simulator consistently.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/build-ios-onnxruntime.sh
Line: 172:172
Comment:
Directory name mismatch causing build failure: This script creates `ios-arm64-simulator` but other components expect `ios-arm64_x86_64-simulator`.
**Impact**: When the build script is used (on cache miss), it creates a directory structure incompatible with:
1. `build.rs` line 12 which looks for `ios-arm64_x86_64-simulator`
2. `setup-ios-onnxruntime.sh` which creates `ios-arm64_x86_64-simulator`
3. The GitHub Actions workflows which reference `ios-arm64-simulator` in the generated cargo config
This will cause linker errors when building for iOS simulator.
```suggestion
mkdir -p "${XCFRAMEWORK_DIR}/ios-arm64_x86_64-simulator"
```
Also update line 180, 222, and 256 to use `ios-arm64_x86_64-simulator` consistently.
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| TAURI_DIR="$(dirname "$SCRIPT_DIR")" | ||
| ORT_VERSION="${ORT_VERSION:-1.20.1}" |
There was a problem hiding this comment.
Version mismatch: This script defaults to ONNX Runtime 1.20.1, but build-ios-onnxruntime.sh defaults to 1.22.2 and the GitHub Actions workflows explicitly use 1.22.2.
Impact: If this script is run locally without specifying a version, it will download 1.20.1 which may be incompatible with the codebase expectations. The build script comment mentions "older versions have Eigen hash mismatch issues with GitLab".
| ORT_VERSION="${ORT_VERSION:-1.20.1}" | |
| ORT_VERSION="${ORT_VERSION:-1.22.2}" |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src-tauri/scripts/setup-ios-onnxruntime.sh
Line: 10:10
Comment:
Version mismatch: This script defaults to ONNX Runtime 1.20.1, but `build-ios-onnxruntime.sh` defaults to 1.22.2 and the GitHub Actions workflows explicitly use 1.22.2.
**Impact**: If this script is run locally without specifying a version, it will download 1.20.1 which may be incompatible with the codebase expectations. The build script comment mentions "older versions have Eigen hash mismatch issues with GitLab".
```suggestion
ORT_VERSION="${ORT_VERSION:-1.22.2}"
```
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Invalid Cargo configuration: The .onnxruntime suffix in section names like [target.aarch64-apple-ios.onnxruntime] is not valid Cargo TOML syntax.
Issue: Cargo only recognizes [target.<triple>] sections with keys like rustc-link-search and rustc-link-lib. The .onnxruntime suffix will be ignored, causing the generated config to be ineffective.
Impact: The linking configuration won't be applied, which may cause:
- Build failures due to missing ONNX Runtime library
- Falls back to
ort-sysattempting to download/build ONNX Runtime itself
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Note: Also fixed directory name to ios-arm64_x86_64-simulator to match build.rs.
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/mobile-build.yml
Line: 97:107
Comment:
Invalid Cargo configuration: The `.onnxruntime` suffix in section names like `[target.aarch64-apple-ios.onnxruntime]` is not valid Cargo TOML syntax.
**Issue**: Cargo only recognizes `[target.<triple>]` sections with keys like `rustc-link-search` and `rustc-link-lib`. The `.onnxruntime` suffix will be ignored, causing the generated config to be ineffective.
**Impact**: The linking configuration won't be applied, which may cause:
- Build failures due to missing ONNX Runtime library
- Falls back to `ort-sys` attempting to download/build ONNX Runtime itself
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
Note: Also fixed directory name to `ios-arm64_x86_64-simulator` to match `build.rs`.
How can I resolve this? If you propose a fix, please make it concise.| [target.aarch64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.aarch64-apple-ios-sim.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] | ||
|
|
||
| [target.x86_64-apple-ios.onnxruntime] | ||
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | ||
| rustc-link-lib = ["static=onnxruntime"] |
There was a problem hiding this comment.
Invalid Cargo configuration: Same .onnxruntime suffix issue as in mobile-build.yml. The section names are invalid and will be ignored by Cargo.
Additionally, the simulator directory path should be ios-arm64_x86_64-simulator to match build.rs expectations.
| [target.aarch64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios.onnxruntime] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.aarch64-apple-ios-sim] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] | |
| [target.x86_64-apple-ios] | |
| rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"] | |
| rustc-link-lib = ["static=onnxruntime"] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/testflight-on-comment.yml
Line: 164:174
Comment:
Invalid Cargo configuration: Same `.onnxruntime` suffix issue as in mobile-build.yml. The section names are invalid and will be ignored by Cargo.
Additionally, the simulator directory path should be `ios-arm64_x86_64-simulator` to match `build.rs` expectations.
```suggestion
[target.aarch64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64"]
rustc-link-lib = ["static=onnxruntime"]
[target.aarch64-apple-ios-sim]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
[target.x86_64-apple-ios]
rustc-link-search = ["${WORKSPACE}/frontend/src-tauri/onnxruntime-ios/onnxruntime.xcframework/ios-arm64_x86_64-simulator"]
rustc-link-lib = ["static=onnxruntime"]
```
How can I resolve this? If you propose a fix, please make it concise.
Summary
Add Text-to-Speech (TTS) support for iOS using ONNX Runtime, enabling the Supertonic TTS model to run on-device on iPhones and iPads.
Changes
ortand other TTS libraries~/Documents/tts_models)Technical Details
Testing
Notes
This is the first step toward iOS TTS. The implementation mirrors the desktop version - users will need to download the TTS models (~264MB) before use.
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.