-
Notifications
You must be signed in to change notification settings - Fork 101
fix(ios-example): fix package dependencies and macOS ONNX Runtime setup #245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Fix RunAnywhereCoreBinary checksum mismatch - Add RunAnywhereAppleAI package dependency - Remove WhisperKit adapter (use ONNX Runtime instead) - Update framework availability UI to show all frameworks - Configure macOS rpath for ONNX Runtime dylib - Clean up model names (remove "[macOS only]" suffix)
📝 WalkthroughWalkthroughRemoves the RunAnywhereWhisperKit product and all WhisperKit imports/registrations from the iOS example; updates Xcode project/package IDs, versioning, bundle/team, package pins, a binary checksum, macOS linker flags, FoundationModels availability/logging, per-framework availability UI, and app theming colors. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important
Looks good to me! 👍
Reviewed everything up to 36abc04 in 45 seconds. Click for details.
- Reviewed
484lines of code in7files - Skipped
0files when reviewing. - Skipped posting
6draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. examples/ios/RunAnywhereAI/Package.swift:58
- Draft comment:
Removed 'RunAnywhereWhisperKit' dependency. Ensure that all references to WhisperKit (both in dependencies and code) are intentionally removed. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the author to ensure that all references to a removed dependency are intentionally removed. This is a request for confirmation, which violates the rules. The comment does not provide a specific code suggestion or point out a specific issue.
2. examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj:477
- Draft comment:
Updated DEVELOPMENT_TEAM, CURRENT_PROJECT_VERSION, and PRODUCT_BUNDLE_IDENTIFIER. Confirm that these changes align with current organizational settings and branding. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to confirm alignment with organizational settings and branding, which falls under asking for confirmation or verification. This violates the rule against asking the PR author to confirm their intention or ensure behavior is intended.
3. examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift:39
- Draft comment:
Removed WhisperKit integration (import and memory cleanup calls). Verify that removal of WhisperKitAdapter does not affect required STT functionality. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift:160
- Draft comment:
Refactored framework filtering to use getFrameworkAvailability. Consider whether unavailable frameworks should be shown (with unavailability reasons), similar to SimplifiedModelsView. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
5. examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift:15
- Draft comment:
Introduced 'frameworkAvailability' state to display unavailability reasons. Ensure consistency in UX with other model views. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment suggests ensuring consistency in UX, which is a general request for confirmation or verification. This violates the rule against asking the PR author to ensure behavior is intended or consistent.
6. sdk/runanywhere-swift/Package.swift:252
- Draft comment:
Updated ONNX Runtime binary target checksum and macOS linker flags. Verify that the new checksum and flags point to the correct binary (and that the rpath is set properly). - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to verify the checksum and linker flags, which falls under asking the author to double-check things. This violates the rules.
Workflow ID: wflow_xsCkRPBkWScCSl1p
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift (2)
124-126: CI failure + security: remove hardcoded API key and fix TODO to reference a GitHub issue.
The linter requires TODOs to reference an issue, and committing an API key placeholder is risky even in an example.- let apiKey = "testing_api_key" // TODO: Get from secure storage + // TODO: #<ISSUE_ID> - Load API key from secure storage / build config (do not hardcode) + let apiKey = (Bundle.main.object(forInfoDictionaryKey: "RUNANYWHERE_API_KEY") as? String) ?? "" + guard !apiKey.isEmpty else { + throw NSError( + domain: "RunAnywhereAIApp", + code: 1, + userInfo: [NSLocalizedDescriptionKey: "Missing RUNANYWHERE_API_KEY (configure in Info.plist / build settings)."] + ) + } let baseURL = "https://api.runanywhere.ai"
176-231: CI failure: replacetry! ModelRegistration(...)with non-crashing construction.
try!is blocked by lint and will crash the app if any URL/validation fails. Preferdo/catch+ logging (orcompactMapwithtry?and explicit error logs).await RunAnywhere.registerFramework( LlamaCPPCoreAdapter(), - models: [ - try! ModelRegistration( + models: [ + (try? ModelRegistration( url: "https://huggingface.co/prithivMLmods/SmolLM2-360M-GGUF/resolve/main/SmolLM2-360M.Q8_0.gguf", framework: .llamaCpp, modality: .textToText, id: "smollm2-360m-q8-0", name: "SmolLM2 360M Q8_0", memoryRequirement: 500_000_000 - ), + ))!, ... ] )Note: the snippet above shows the mechanical change, but you should not keep
))!—instead, build[ModelRegistration]viado/catchorcompactMapand log failures, e.g.let models = [ ... ].compactMap { $0 }. I can draft the full safe rewrite for both development + production blocks if you want.Also applies to: 233-280
🧹 Nitpick comments (2)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift (1)
125-160: Consider separating “still loading” vs “loaded but no adapters registered”.
Right now,frameworkAvailability.isEmptyshows both a spinner and a “No framework adapters…” message; a dedicatedisLoadingFrameworksflag (or “loadedOnce”) would avoid mixed signals.examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift (1)
42-46: Log message is now misleading (says “cleaning up” but does nothing).
If cleanup is SDK-managed, consider adjusting the log text to “memory pressure detected” (or call an SDK hook if one exists).Also applies to: 75-78
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
examples/ios/RunAnywhereAI/Package.swift(0 hunks)examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj(9 hunks)examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved(3 hunks)examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift(6 hunks)examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift(1 hunks)examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift(4 hunks)sdk/runanywhere-swift/Package.swift(1 hunks)
💤 Files with no reviewable changes (1)
- examples/ios/RunAnywhereAI/Package.swift
🧰 Additional context used
📓 Path-based instructions (2)
**/*.swift
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.swift: Use the latest Swift 6 APIs always.
Do not use NSLock as it is outdated. Use Swift 6 concurrency primitives instead.
Files:
sdk/runanywhere-swift/Package.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift
sdk/runanywhere-swift/**/Package.swift
📄 CodeRabbit inference engine (CLAUDE.md)
sdk/runanywhere-swift/**/Package.swift: iOS minimum deployment target must be 13.0 or later for Swift SDK.
Swift minimum version must be 5.9 or later for iOS SDK.
Files:
sdk/runanywhere-swift/Package.swift
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Applied to files:
sdk/runanywhere-swift/Package.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedexamples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
Applied to files:
sdk/runanywhere-swift/Package.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolvedexamples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj
🧬 Code graph analysis (2)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift (2)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/events/SDKEvent.kt (1)
availability(209-209)examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
toggleFramework(449-457)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/RunAnywhere+Frameworks.swift (1)
getFrameworkAvailability(103-115)
🪛 GitHub Actions: iOS App CI
examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift
[error] 124-124: TODO Must Reference GitHub Issue Violation: TODOs must reference a GitHub issue (e.g., // TODO: #123 - Description) (todo_with_issue)
[error] 181-181: Force Try Violation: Force tries should be avoided (force_try)
⏰ 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). (2)
- GitHub Check: Greptile Review
- GitHub Check: Analyze (swift)
🔇 Additional comments (8)
examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved (2)
32-38: PinningFluidAudiotobranch: mainis brittle—prefer a tag/commit-only strategy if possible.
Even with a pinnedrevision, keepingbranch: "main"tends to cause surprise diffs on futurePackage.resolvedregenerations. Consider switching to an exact revision-only approach (or a tagged version) if the upstream supports it.
2-2: Dependency bumps: please confirm compatibility and why they’re needed.
originHashand the GRDB / swift-asn1 pins changed; make sure this is intentional (not just a regenerated lockfile) and that the iOS example still builds cleanly with the updated graph.Also applies to: 41-47, 76-83
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift (1)
16-19: Good shift to availability-based data model (and reason support).
DerivingavailableFrameworksfrom availability keeps older logic working while enabling richer UI.Also applies to: 66-74
sdk/runanywhere-swift/Package.swift (1)
251-255: Verify binary target checksum matches the release artifact before merging.The checksum for
RunAnywhereCoreBinaryat lines 251-255 must correspond to the exact.zipartifact at the configured URL, or SwiftPM will fail during installation. Compute and confirm locally:swift package compute-checksum /path/to/RunAnywhereCore.xcframework.zipand verify it matches:
0786d494553226820a3a19ba5ee573d4bedf4096b9ebfae9010b621952bb617bexamples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj (4)
10-14: LGTM! Package dependency references updated correctly.The updated package reference IDs are consistent throughout the project file and properly link the Swift packages (RunAnywhere, RunAnywhereONNX, RunAnywhereLlamaCPP, RunAnywhereFluidAudio, RunAnywhereAppleAI) to the local package at
../../../sdk/runanywhere-swift. The removal of RunAnywhereWhisperKit aligns with the PR objectives.Also applies to: 67-71, 144-148, 231-231, 691-691, 698-722
503-503: LGTM! Marketing version bumped appropriately.The
MARKETING_VERSIONupdate from 0.13.0 to 0.14.0 is consistent with the minor version increment and aligns with the removal of WhisperKit and other dependency changes in this PR.Also applies to: 548-548
480-480: Development team is already set to L86FH3K93L with proper configuration.The
DEVELOPMENT_TEAMis configured toL86FH3K93Lin both Debug and Release configurations (lines 480, 525), withCODE_SIGN_STYLE = Automaticand entitlements properly specified. Test targets correctly have emptyDEVELOPMENT_TEAM. No uncommitted changes are present. The configuration appears stable and complete.
498-501: Intel Mac incompatibility:/opt/homebrew/libonly exists on Apple Silicon.The
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]configuration at lines 498-501 and 543-546 hardcodes a path that breaks macOS builds on Intel Macs. While/opt/homebrewis exclusively for Apple Silicon (Intel Macs use/usr/local), this affects only the macOS variant of the app—iOS builds use a separateLD_RUNPATH_SEARCH_PATHSsetting unaffected by this change.If Intel Mac support is required for macOS builds, consider:
- Bundle ONNX Runtime libraries directly in the app and use
@rpath- Conditional build paths: Detect architecture at build time and adjust the library path
- Remove system dependency: Use framework embedding instead of relying on system-installed libraries
Current approach limits macOS builds to Apple Silicon only.
| MARKETING_VERSION = 0.13.0; | ||
| PRODUCT_BUNDLE_IDENTIFIER = com.runanywhere.RunAnywhereAI; | ||
| MARKETING_VERSION = 0.14.0; | ||
| PRODUCT_BUNDLE_IDENTIFIER = com.runanywhere.RunAnywhere; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, locate and examine the .pbxproj file
find . -name "project.pbxproj" -type fRepository: RunanywhereAI/runanywhere-sdks
Length of output: 294
🏁 Script executed:
# Check the specific lines mentioned in the review
cat -n examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj | sed -n '500,510p'Repository: RunanywhereAI/runanywhere-sdks
Length of output: 538
🏁 Script executed:
# Also check line 549
cat -n examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj | sed -n '545,555p'Repository: RunanywhereAI/runanywhere-sdks
Length of output: 538
🏁 Script executed:
# Search for any migration code related to bundle ID or keychain
rg -i "migration|keychain|UserDefaults|bundle" --type swift --type objc examples/ios/Repository: RunanywhereAI/runanywhere-sdks
Length of output: 6023
🏁 Script executed:
# Check if there are any comments or documentation about this change
rg -i "RunAnywhereAI|RunAnywhere|bundle.*identifier" examples/ios/ -B 2 -A 2Repository: RunanywhereAI/runanywhere-sdks
Length of output: 50389
🏁 Script executed:
# Look at git history if available to understand the change rationale
git log --oneline -20 examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj 2>/dev/null || echo "Git history not available or file not tracked"Repository: RunanywhereAI/runanywhere-sdks
Length of output: 154
🏁 Script executed:
# Check the exact KeychainHelper service string
cat -n examples/ios/RunAnywhereAI/RunAnywhereAI/Utilities/KeychainHelper.swift | head -30Repository: RunanywhereAI/runanywhere-sdks
Length of output: 1061
🏁 Script executed:
# Check run.sh to see the bundle ID there
cat -n examples/ios/RunAnywhereAI/run.sh | grep -i "bundle\|com\."Repository: RunanywhereAI/runanywhere-sdks
Length of output: 149
🏁 Script executed:
# Search for any data migration code
rg -i "migration|migrate|keychain.*old|old.*keychain" examples/ios/ -A 2 -B 2Repository: RunanywhereAI/runanywhere-sdks
Length of output: 56
🏁 Script executed:
# Check what's actually being stored in keychain
rg "KeychainHelper\.|KeychainService\." examples/ios/ -B 2 -A 2Repository: RunanywhereAI/runanywhere-sdks
Length of output: 7525
🏁 Script executed:
# Check KeychainService.swift
cat -n examples/ios/RunAnywhereAI/RunAnywhereAI/Core/Services/KeychainService.swift | head -40Repository: RunanywhereAI/runanywhere-sdks
Length of output: 1391
🏁 Script executed:
# Search for service identifier in KeychainService
rg "service|Service.*=" examples/ios/RunAnywhereAI/RunAnywhereAI/Core/Services/KeychainService.swift -A 2 -B 2Repository: RunanywhereAI/runanywhere-sdks
Length of output: 56
Update KeychainHelper service identifier to match new bundle ID or implement migration.
Changing PRODUCT_BUNDLE_IDENTIFIER from com.runanywhere.RunAnywhereAI to com.runanywhere.RunAnywhere creates a keychain data loss issue:
- KeychainHelper (line 13) has hardcoded
service = "com.runanywhere.RunAnywhereAI"— theanalyticsLogToLocalsetting stored under the old service identifier will become inaccessible - UserDefaults (temperature, maxTokens, routingPolicy) will migrate automatically as they don't use bundle ID scope
- KeychainService (API key) is unaffected as it doesn't use service identifier scoping
Either update KeychainHelper.service to the new bundle ID com.runanywhere.RunAnywhere or add migration code to recover the stored analytics preference from the old service identifier before deletion.
Also applies to: 549-549
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additional Comments (1)
-
examples/ios/RunAnywhereAI/RunAnywhereAI.xcodeproj/project.pbxproj, line 566-571 (link)logic: Test target versions are inconsistent - still at version 5 and 0.13.0 while main app is at version 6 and 0.14.0
7 files reviewed, 1 comment
- Fix ONNX Runtime CoreML linker error with dynamic lookup - Update Foundation Models availability to macOS 26.0 - Add error dialogs with Apple Intelligence setup instructions - Improve error messages and diagnostics throughout
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important
Looks good to me! 👍
Reviewed 85a9a78 in 1 minute and 48 seconds. Click for details.
- Reviewed
428lines of code in5files - Skipped
0files when reviewing. - Skipped posting
6draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift:565
- Draft comment:
Consider refactoring the error extraction logic in selectAndLoadModel into a dedicated helper function. This would reduce duplication and ensure consistent error messaging (e.g. handling of error code -3) across the app. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The comment suggests refactoring for code quality, which is generally good. However, it mentions "reduce duplication" and "ensure consistent error messaging across the app", implying this pattern exists elsewhere. But I can only see this error handling in one location in the diff. The rules state I should "ignore cross-file issues" and only think about the file being reviewed. Without evidence of duplication within this file, the comment is speculative about duplication "across the app". The refactoring suggestion might be premature optimization if this is the only place this error handling occurs. The comment also doesn't provide clear, actionable guidance - it's more of a general suggestion. The error handling logic appears only once in this file based on the diff. The comment assumes duplication exists "across the app" without showing evidence in this file. This could be a cross-file concern that I should ignore per the rules. Also, refactoring suggestions should be clearly actionable, but this is somewhat vague about where the duplication is. While the comment is about code quality (which is good), it makes assumptions about duplication across the app that aren't visible in this file's diff. The rules explicitly state to ignore cross-file issues. If there's no duplication within this file, the refactoring suggestion is premature and speculative. The comment doesn't provide strong evidence that this refactoring is necessary now. This comment should be deleted. It suggests refactoring based on assumed duplication "across the app" without evidence in this file. Per the rules, I should ignore cross-file issues and only consider this file. The error handling appears only once in this diff, making the refactoring suggestion speculative rather than clearly necessary.
2. sdk/runanywhere-swift/Package.swift:165
- Draft comment:
The ONNXRuntime target now adds the '-Wl,-undefined,dynamic_lookup' flag for macOS. Ensure that this dynamic symbol resolution does not inadvertently mask unresolved symbols that should be caught at build/runtime. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to ensure that a specific behavior is intended, which violates the rules. It does not provide a specific suggestion or ask for a specific test to be written. Therefore, it should be removed.
3. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift:10
- Draft comment:
Availability requirements were updated to iOS 18.0+ (macOS 26.0+). Please verify that FoundationModels framework features work as expected on iOS 18.0 given its documentation and hardware requirements. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%This comment is asking the PR author to verify that the features work as expected on a specific iOS version, which falls under the rule of not asking the author to ensure behavior is intended or tested. It does not provide a specific code suggestion or point out a specific issue.
4. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift:60
- Draft comment:
The switch statement handling model.availability provides detailed error messages with specific error codes. Ensure that these error codes (-2, -3, -4, etc.) are consistently documented and handled at the UI level for clarity. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
5. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift:274
- Draft comment:
The token extraction logic in streamGenerate correctly sends only new tokens by comparing the current and previous content. Consider adding safeguards in case the aggregated response unexpectedly resets or shrinks. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
6. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift:48
- Draft comment:
In the canHandle(modelId:) method, the use of simple string contains checks for identifiers like 'foundation' or 'apple' may lead to false positives. Consider more robust or stricter matching criteria for Foundation Models IDs. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
Workflow ID: wflow_FcAzWLQw9XOYo4hN
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift (1)
42-45: Fix comment/behavior mismatch for nil/emptymodelId.
Comment says nil/empty will “use default Foundation Model”, but the code returnsfalseand explicitly defers to other providers. Either update the comment or change behavior (and document who should handle nil/empty).
♻️ Duplicate comments (1)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
188-199: Comment/behavior mismatch: code filters out unavailable frameworks but comment says they're shown.The comment on line 189 states that unavailable frameworks are shown, but line 196 filters by
availability.isAvailable, removing them from the list. Either:
- Update the comment to "Only shows available frameworks for actual use"
- Or remove the
availability.isAvailablecheck to match the comment
🧹 Nitpick comments (4)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
564-591: Consider extracting error message handling to a helper function.The nested error handling logic could be simplified by extracting it to a dedicated function:
private func extractErrorMessage(from error: Error) -> String { // Check for Apple Intelligence error (FoundationModels domain, code -3) if let nsError = error as NSError?, nsError.domain == "FoundationModels", nsError.code == -3 { return nsError.localizedDescription } // Check for LLMServiceError with underlying error if let llmError = error as? LLMServiceError { switch llmError { case .generationFailed(let underlyingError): if let nsError = underlyingError as NSError?, nsError.domain == "FoundationModels", nsError.code == -3 { return nsError.localizedDescription } return underlyingError.localizedDescription default: return llmError.localizedDescription } } return error.localizedDescription }Then simplify lines 564-590 to:
errorMessage = extractErrorMessage(from: error) showErrorAlert = trueThis improves readability and makes the error handling logic testable.
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (3)
16-19:supportedFormatscontradicts its own comment and may mislead format-based routing.
You say “doesn't use file formats - it's built-in” but return.mlmodel/.mlpackage. If other parts of the SDK usesupportedFormatsto decide file compatibility, this could cause incorrect selection. Consider returning[](or a dedicated “built-in/none” format if the SDK has one) and documenting the semantics.
53-66: Reduce repeated lowercasing + keep matching consistent.
Minor:model.name.lowercased()is computed twice; store it once to reduce churn and keep the expression readable.
74-96: Revisit the error type for “modality not supported”.
LLMServiceError.modelNotFound("modality not supported")reads misleading (the model exists; modality doesn’t). If there’s anunsupportedModality/invalidRequest-style error in the SDK, prefer that; otherwise consider adding one.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift(5 hunks)sdk/runanywhere-swift/Package.swift(2 hunks)sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift(4 hunks)sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift(3 hunks)sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- sdk/runanywhere-swift/Package.swift
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.swift: Use the latest Swift 6 APIs always.
Do not use NSLock as it is outdated. Use Swift 6 concurrency primitives instead.
Files:
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to **/*.swift : Use the latest Swift 6 APIs always.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
🧬 Code graph analysis (1)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (2)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift (1)
canHandle(36-53)sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
initialize(31-188)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (swift)
🔇 Additional comments (4)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (2)
10-12: LGTM: Platform-specific import properly gated.The conditional import of AppKit for macOS is correct and necessary for the NSWorkspace usage later in the file.
57-58: LGTM: Error state variables follow SwiftUI best practices.The state variables for error presentation are appropriately named and will work correctly with the alert modifier.
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (1)
29-42: Registration path looks good; keep the logs but confirmcanImport(FoundationModels)coverage.
The#if canImport(FoundationModels)+#availableguard is the right shape for safe registration, and the “unavailable” warning is helpful. Please just confirm consumers won’t treat “registered adapter” as proof the framework is usable (since this now logs and returns early).sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
31-41: Initialization diagnostics + structured error mapping are a solid improvement.
The detailed messages for.deviceNotEligible,.appleIntelligenceNotEnabled,.modelNotReady, etc., plus rethrowingLLMServiceErrorverbatim, should make failures much easier to debug in real apps.Also applies to: 50-181, 184-187
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift
Show resolved
Hide resolved
| /// Adapter for Apple's native Foundation Models framework (iOS 18.0+, macOS 26.0+) | ||
| /// Uses Apple's built-in language models without requiring external model files | ||
| @available(iOS 26.0, macOS 26.0, *) | ||
| @available(iOS 18.0, macOS 26.0, *) | ||
| public class FoundationModelsAdapter: UnifiedFrameworkAdapter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the FoundationModelsServiceProvider.swift file
find . -name "FoundationModelsServiceProvider.swift" -type fRepository: RunanywhereAI/runanywhere-sdks
Length of output: 167
🏁 Script executed:
# Check the current file structure and find related FoundationModels files
find sdk/runanywhere-swift -name "*FoundationModels*" -type fRepository: RunanywhereAI/runanywhere-sdks
Length of output: 333
🏁 Script executed:
# Search for @available annotations in the Swift SDK to see the pattern
rg "@available" sdk/runanywhere-swift --type swift -B 2Repository: RunanywhereAI/runanywhere-sdks
Length of output: 2862
🌐 Web query:
Apple FoundationModels framework minimum iOS macOS requirements API availability
💡 Result:
-
Minimum OS: iOS 26 / iPadOS 26 / macOS 26 (visionOS 26 also supported). Apple Intelligence must be enabled and the device must be Apple‑Intelligence–compatible. [1][2]
-
API availability checks: use the framework’s availability properties/APIs (e.g., SystemLanguageModel.default.isAvailable and model.availability / availability enum) and the usual @available checks (e.g., #available(iOS 26.0, macOS 26.0, *)). Check at runtime because model download/region/language and Apple Intelligence settings can make it unavailable even on supported OS/devices. [1][3]
Sources:
- Apple Newsroom — “Apple’s Foundation Models framework … available with iOS 26, iPadOS 26, and macOS 26.” [1]
- Apple developer code-along / docs examples showing SystemLanguageModel and availability checks. [3]
🏁 Script executed:
# Let's examine the FoundationModelsServiceProvider.swift file to see the full context
cat -n sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swiftRepository: RunanywhereAI/runanywhere-sdks
Length of output: 3498
🏁 Script executed:
# Check Package.swift to see deployment target constraints
find sdk/runanywhere-swift -name "Package.swift" -type f -exec cat -n {} +Repository: RunanywhereAI/runanywhere-sdks
Length of output: 13172
Correct @available(iOS 18.0, macOS 26.0, *) to match actual FoundationModels requirements: iOS 26.0, macOS 26.0.
Package.swift documentation confirms "iOS 26+ runtime" but @available annotations use iOS 18.0, creating a version mismatch. Apple's official documentation confirms Foundation Models requires iOS 26+ and macOS 26+ (not iOS 18.0).
🤖 Prompt for AI Agents
In
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift
around lines 10 to 13, the @available annotation incorrectly lists iOS 18.0;
change it to match FoundationModels requirements by updating the annotation to
@available(iOS 26.0, macOS 26.0, *). Replace the existing iOS version only (keep
macOS 26.0 and the wildcard) so the class availability aligns with Package.swift
and Apple docs, and run a quick build to confirm no other availability
mismatches remain.
| @available(iOS 18.0, macOS 26.0, *) | ||
| public class FoundationModelsService: LLMService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Availability gating likely wrong on macOS (macOS 26.0)—please verify with Apple docs / Xcode SDK.
This is now enforced both via @available and a runtime guard, so an incorrect macOS version will fully disable the feature there.
Also applies to: 44-48
🤖 Prompt for AI Agents
In
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift
around lines 11-12 (and also adjust the same mismatch at lines 44-48), verify
the correct macOS availability version against the installed Xcode SDK/Apple
docs and make the @available annotation and the runtime availability guard
consistent: if the feature is actually introduced in a different macOS release
than 26.0, change both the @available(...) macOS version and the runtime guard
to the correct version number so they match; if you cannot confirm the exact SDK
number during review, replace the hardcoded guard with a feature-detection
approach (e.g., use API-specific selectors/availability checks or compile-time
checks) and add a short comment referencing the Apple docs used for
verification.
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important
Looks good to me! 👍
Reviewed 2f1b78d in 49 seconds. Click for details.
- Reviewed
2203lines of code in15files - Skipped
0files when reviewing. - Skipped posting
4draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift:53
- Draft comment:
Consider extracting the hard-coded model identifier checks (e.g. 'foundation-models-default', 'apple') into named constants or a configuration structure for better maintainability and consistency. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
2. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift:79
- Draft comment:
The detailed multi-line error messages for unavailable Apple Intelligence are very helpful; consider centralizing these user instructions (or localizing them) to avoid duplication and simplify future updates. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift:224
- Draft comment:
Error handling in the generation methods (both streaming and non-streaming) includes similar context window checks. Consider refactoring these checks into a helper function to reduce code duplication and enhance clarity. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift:55
- Draft comment:
In createLLMService(configuration:), consider allowing injection of a hardware configuration (if available) so that the FoundationModelsService can be optimized based on the device’s capabilities. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
Workflow ID: wflow_V4thuvSTC31ThXot
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 (3)
examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift (3)
212-239: Handle ModelRegistration errors gracefully instead of crashing.The ONNX model registrations also use
try!, which will crash the app if any ModelRegistration fails. Apply the same error handling approach suggested for the LlamaCPP models above.
290-316: Handle ModelRegistration errors gracefully instead of crashing.The production ONNX model registrations also use
try!. Apply the same error handling approach suggested earlier to prevent app crashes during initialization.
333-333: Update log message to use consistent "curated models" terminology.Line 333 refers to "hardcoded models" while other log messages throughout the file use "curated models" terminology (lines 174, 205, 262, 284, 319). Update this for consistency.
🔎 Suggested fix
- logger.info("🎉 All adapters registered for production with hardcoded models") + logger.info("🎉 All adapters registered for production with curated models")
♻️ Duplicate comments (4)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
184-193: Comment still inconsistent with code behavior.The comment on line 185 says "shows all frameworks, including unavailable ones" but the code on lines 189-193 filters to only include available frameworks (
availability.isAvailable). Update the comment to accurately reflect the filtering behavior.sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (1)
12-13: Comment contradicts availability annotation.Line 12 states "requires iOS 26.0+ or macOS 26.0+" but the
@availableannotation on line 13 only specifiesiOS 26.0, *. This inconsistency propagates through runtime guards at lines 33 and 48, and the model description at line 139.Align the annotation with the comment, or update documentation to reflect iOS-only support.
🔎 Option: Add macOS to availability if supported
/// Note: Foundation Models (Apple Intelligence) requires iOS 26.0+ or macOS 26.0+ -@available(iOS 26.0, *) +@available(iOS 26.0, macOS 26.0, *) public class FoundationModelsAdapter: UnifiedFrameworkAdapter {sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
11-11: Availability annotation inconsistent with runtime guards and macOS code paths.The class is marked
@available(iOS 26.0, *)(iOS-only), but multiple runtime guards throughout this file still check#available(iOS 26.0, macOS 26.0, *)at lines 44, 198, and 257. Additionally, there's extensive macOS-specific code (lines 38-41, 90-107, 114-119, 139-154) that becomes unreachable.Either:
- Add
macOS 26.0to the@availableannotation if macOS is supported, or- Remove all macOS-specific code paths and runtime guards if macOS is intentionally unsupported.
🔎 Option 1: Add macOS support to availability
-@available(iOS 26.0, *) +@available(iOS 26.0, macOS 26.0, *) public class FoundationModelsService: LLMService {sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift (1)
36-40: Runtime guard inconsistent with class availability.The class is marked
@available(iOS 26.0, *)at line 16, but this runtime guard checks formacOS 26.0. Since the class itself isn't available on macOS, this macOS check is unreachable.🔎 Align with class availability (iOS-only)
public func canHandle(modelId: String?) -> Bool { - // Check if we're running on iOS 26.0+ - guard #available(iOS 26.0, macOS 26.0, *) else { + // Check if we're running on iOS 26.0+ (macOS not supported at class level) + guard #available(iOS 26.0, *) else { return false }Alternatively, if macOS support is intended, add
macOS 26.0to the@availableannotations at lines 16 and 79.
🧹 Nitpick comments (7)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelStatusComponents.swift (1)
91-109: Consider removing unused helper functions.The
frameworkIcon(for:)andframeworkColor(for:)functions inModelStatusBannerappear to be dead code after the UI simplification that removed framework-specific icon/color display from the loaded state.examples/ios/RunAnywhereAI/RunAnywhereAI/App/ContentView.swift (1)
64-64: Consider usingtint(_:)instead ofaccentColor(_:).
accentColor(_:)is deprecated in iOS 15+. Consider using.tint(AppColors.primaryAccent)for forward compatibility.🔎 Proposed fix
- .accentColor(AppColors.primaryAccent) + .tint(AppColors.primaryAccent)examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swift (1)
235-257: Consider removing unused computed properties.The
statusColorandstatusTextcomputed properties appear to be unused in this view (not referenced in thebody). If they're not needed elsewhere, consider removing them to reduce dead code.#!/bin/bash # Check if statusColor or statusText are referenced anywhere in the codebase rg -n "statusColor|statusText" examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/TextToSpeechView.swift (1)
597-607: Consider modernizing Timer to async/await pattern.The
Timer.scheduledTimerwith closure pattern works, but the nestedTask { @MainActor in }is redundant sinceTTSViewModelis already@MainActor. Additionally, for Swift 6 compatibility, consider using an async Task withTask.sleepfor periodic updates:🔎 Optional refactor using async pattern
- private func startPlayback() { - guard let player = audioPlayer else { return } - - player.play() - isPlaying = true - - // Start playback timer - playbackTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in - Task { @MainActor in - guard let self = self, let player = self.audioPlayer else { return } - self.currentTime = player.currentTime - self.playbackProgress = player.currentTime / player.duration - if !player.isPlaying { - self.stopPlayback() - } - } - } - } + private var playbackTask: Task<Void, Never>? + + private func startPlayback() { + guard let player = audioPlayer else { return } + + player.play() + isPlaying = true + + // Start playback monitoring with async Task + playbackTask = Task { + while !Task.isCancelled, let player = self.audioPlayer, player.isPlaying { + self.currentTime = player.currentTime + self.playbackProgress = player.currentTime / player.duration + try? await Task.sleep(for: .milliseconds(100)) + } + if !Task.isCancelled { + self.stopPlayback() + } + } + }Then update
stopPlayback()to cancelplaybackTask?.cancel()instead of invalidating the timer.examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift (1)
432-447: Consider extracting duplicate tar.bz2 error handling into a helper.The tar.bz2 error detection and message formatting logic is duplicated in both the progress callback failure case and the catch block. Extracting this to a private helper would reduce duplication and improve maintainability.
🔎 Proposed refactor to extract helper
Add a helper method to
ModelRow:#if os(iOS) private func formatDownloadError(_ error: Error, for model: ModelInfo) -> String { let errorDescription = error.localizedDescription if let downloadURL = model.downloadURL, downloadURL.contains(".tar.bz2") || errorDescription.lowercased().contains("bz2") || errorDescription.lowercased().contains("extraction") { return "This model uses .tar.bz2 format which cannot be extracted on iOS. Please use a different STT model format or try on macOS." } return errorDescription } #else private func formatDownloadError(_ error: Error, for model: ModelInfo) -> String { return error.localizedDescription } #endifThen simplify both error paths:
case .failed(let error): await MainActor.run { self.downloadProgress = 0.0 self.isDownloading = false - - // Check if this is a tar.bz2 extraction error on iOS - let errorDescription = error.localizedDescription - var userMessage = errorDescription - - #if os(iOS) - if let downloadURL = model.downloadURL, downloadURL.contains(".tar.bz2") || - errorDescription.lowercased().contains("bz2") || - errorDescription.lowercased().contains("extraction") { - userMessage = "This model uses .tar.bz2 format which cannot be extracted on iOS. Please use a different STT model format or try on macOS." - } - #endif - - self.downloadErrorMessage = "Failed to download \(model.name): \(userMessage)" + self.downloadErrorMessage = "Failed to download \(model.name): \(formatDownloadError(error, for: model))" self.showDownloadError = trueAlso applies to: 461-476
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
211-214: Semantically incorrect error for busy session.Throwing
notInitializedwhen the session is already responding is misleading—the service is initialized, it's just busy. Consider using a more appropriate error.🔎 Suggested improvement
if sessionObj.isResponding { logger.warning("Session is already responding to another request") - throw LLMServiceError.notInitialized + throw LLMServiceError.generationFailed(NSError(domain: "FoundationModels", code: -9, userInfo: [NSLocalizedDescriptionKey: "Session is busy responding to another request"])) }sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (1)
17-20: Comment contradicts return value.The comment states "Foundation Models doesn't use file formats - it's built-in" but the property returns
[.mlmodel, .mlpackage]. If these formats aren't actually used, consider returning an empty array or clarifying the comment.🔎 Clarify the intent
public var supportedFormats: [ModelFormat] { - // Foundation Models doesn't use file formats - it's built-in - [.mlmodel, .mlpackage] + // Foundation Models doesn't load external files, but we report these formats + // for compatibility with the adapter interface + [.mlmodel, .mlpackage] }Or if truly unused:
public var supportedFormats: [ModelFormat] { - // Foundation Models doesn't use file formats - it's built-in - [.mlmodel, .mlpackage] + // Foundation Models is built-in and doesn't load external model files + [] }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (37)
examples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/100.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/102.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/1024.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/108.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/114.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/120.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/128.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/144.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/152.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/16.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/167.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/172.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/180.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/196.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/20.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/216.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/234.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/256.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/258.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/29.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/32.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/40.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/48.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/50.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/512.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/55.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/57.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/58.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/60.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/64.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/66.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/72.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/76.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/80.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/87.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/88.pngis excluded by!**/*.pngexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/92.pngis excluded by!**/*.png
📒 Files selected for processing (15)
examples/ios/RunAnywhereAI/RunAnywhereAI/App/ContentView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/Contents.jsonexamples/ios/RunAnywhereAI/RunAnywhereAI/Core/DesignSystem/AppColors.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Chat/ChatInterfaceView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelStatusComponents.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Settings/CombinedSettingsView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/TextToSpeechView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/VoiceAssistantView.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.swift: Use the latest Swift 6 APIs always.
Do not use NSLock as it is outdated. Use Swift 6 concurrency primitives instead.
Files:
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/TextToSpeechView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/VoiceAssistantView.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Settings/CombinedSettingsView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/App/ContentView.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Chat/ChatInterfaceView.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelStatusComponents.swiftexamples/ios/RunAnywhereAI/RunAnywhereAI/Core/DesignSystem/AppColors.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : iOS minimum deployment target must be 13.0 or later for Swift SDK.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-swift/**/Package.swift : Swift minimum version must be 5.9 or later for iOS SDK.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to **/*.swift : Use the latest Swift 6 APIs always.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swiftsdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/*.gradle.kts : Android minSdk must be 24 or later for Kotlin Multiplatform SDK.
Applied to files:
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift
🧬 Code graph analysis (5)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
sdk/runanywhere-react-native/src/Public/Errors/SDKError.ts (1)
generationFailed(60-66)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swift (1)
sdk/runanywhere-kotlin/src/commonMain/kotlin/com/runanywhere/sdk/components/voiceagent/VoiceAgentComponent.kt (1)
isProcessing(407-407)
examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift (1)
sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/RunAnywhere+Frameworks.swift (1)
registerFramework(31-67)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (1)
sdk/runanywhere-swift/Sources/RunAnywhere/Public/Extensions/RunAnywhere+Frameworks.swift (1)
getFrameworkAvailability(103-115)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (2)
sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift (1)
canHandle(36-53)sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
initialize(31-188)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (swift)
🔇 Additional comments (38)
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelStatusComponents.swift (4)
37-44: LGTM!The simplified model loaded state with a consistent green checkmark and model name improves UI clarity.
120-177: LGTM!The enhanced
ModelRequiredOverlaywith gradient styling, updated icons, and privacy note provides a polished onboarding experience.
189-223: LGTM!The updated modality properties with consistent styling using
AppColorsalign well with the new design system.
415-417: LGTM!Simplifying the subtitle to show only the model name improves readability.
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/ModelSelectionSheet.swift (5)
10-12: LGTM!Conditional AppKit import for macOS is correctly guarded.
83-97: LGTM!The error alert with the correct URL scheme (
x-apple.systempreferences:com.apple.Siri) for opening Apple Intelligence settings on macOS is properly implemented.
559-586: LGTM!The enhanced error handling correctly extracts user-friendly messages from FoundationModels errors, including the Apple Intelligence not enabled case (error code -3).
692-703: LGTM!The tar.bz2 warning indicator on iOS provides helpful guidance that this format cannot be extracted on mobile devices.
810-854: LGTM!The download error handling with tar.bz2-specific messaging for iOS is well-implemented and provides actionable user guidance.
examples/ios/RunAnywhereAI/RunAnywhereAI/Core/DesignSystem/AppColors.swift (3)
19-29: LGTM!The hex color extension is a clean, reusable utility for the design system.
32-78: LGTM!The color palette is well-organized with clear categorization. Platform-adaptive backgrounds using system colors ensure proper dark mode support.
219-247: LGTM!Framework-specific badge color functions provide a centralized way to maintain consistent styling across the app.
examples/ios/RunAnywhereAI/RunAnywhereAI/App/ContentView.swift (1)
27-35: LGTM!The updated tab labels "Transcribe" and "Speak" are more user-friendly and descriptive than the technical abbreviations "STT" and "TTS".
examples/ios/RunAnywhereAI/RunAnywhereAI/Assets.xcassets/AppIcon.appiconset/Contents.json (1)
1-1: Verify this asset catalog format is intentional.The JSON has been reformatted to a single line with a non-standard
"folder"field added to each image entry. This appears to be output from an icon generation tool. While Xcode should ignore unknown fields, this format reduces maintainability. Consider whether the standard multi-line format without thefolderfield would be preferable.examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/VoiceAssistantView.swift (3)
67-69: LGTM!The ModelBadge color updates consistently use the new AppColors design system.
Also applies to: 259-261
481-509: LGTM!The
micButtonColorandstatusColorcomputed properties now use AppColors consistently, aligning with the centralized design system.
554-554: LGTM!The assistant bubble fill color update maintains visual consistency with the brand palette.
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Settings/CombinedSettingsView.swift (3)
61-62: LGTM!Renaming "SDK Configuration" to "AI Settings" is more user-friendly and aligns with the app's focus on AI capabilities.
Also applies to: 208-209
174-174: LGTM!The simplified analytics description removes unnecessary technical detail about debugging.
688-714: LGTM!The simplified model details view focuses on user-relevant information (download date, last used, size) while removing technical details like format, framework, and file path.
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/SpeechToTextView.swift (3)
77-77: LGTM!The ready state mic icon color update aligns with the AppColors design system.
137-141: LGTM!The TRANSCRIBING badge color updates to AppColors.statusOrange provide consistent styling.
186-187: LGTM!The AdaptiveMicButton color updates properly use AppColors for consistent theming.
examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Voice/TextToSpeechView.swift (3)
10-48: LGTM!The renamed
sampleTTSTextsarray is well-organized with a clear separation between humorous texts and on-device AI facts. The naming change fromfunnyTTSSampleTextstosampleTTSTextsbetter reflects the mixed content.
54-55: LGTM!The UI theming updates consistently use
AppColorstokens throughout the view, improving maintainability and ensuring visual consistency with the design system. The random text selection with fallback is appropriately handled.Also applies to: 121-134, 152-172
325-335: LGTM!The
statusColorcomputed property now consistently usesAppColorstokens, aligning with the centralized design system.examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Models/SimplifiedModelsView.swift (3)
66-73: LGTM!The refactored
loadAvailableFrameworks()now properly usesgetFrameworkAvailability()to provide detailed availability information while maintaining backward compatibility by extractingavailableFrameworksfrom the filtered results.
141-157: LGTM!The framework availability UI now displays helpful unavailability reasons, giving users clear feedback on why certain frameworks aren't available. This is a good UX improvement.
391-397: LGTM!The download error alert provides clear user feedback with a simple dismissal pattern. The
.cancelrole for the OK button is appropriate.examples/ios/RunAnywhereAI/RunAnywhereAI/Features/Chat/ChatInterfaceView.swift (4)
162-166: LGTM!Changing the alert title from "Debug Info" to "Details" is more user-friendly and appropriate for a consumer-facing app.
173-238: LGTM!The redesigned empty state provides an excellent onboarding experience with:
- Welcoming visual hierarchy with gradient icon
- Friendly copy with emoji
- Actionable suggestion chips for quick starts
This is a significant UX improvement for new users.
1371-1398: LGTM!The
SuggestionChipcomponent is clean and reusable with proper use of design system tokens. UsingButtonensures built-in accessibility support.
800-803: LGTM!The model badge styling now uses
AppColors.primaryAccentfor the gradient andAppColors.shadowModelBadgefor the shadow, maintaining consistency with the centralized design system.sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsService.swift (1)
173-180: Good error handling pattern.The catch block properly distinguishes between
LLMServiceError(re-thrown as-is) and other errors (wrapped withgenerationFailed). This preserves error context appropriately.sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsServiceProvider.swift (1)
22-28: Registration pattern is appropriate.The singleton with
@MainActorregistration is the correct pattern for thread-safe module registration.sdk/runanywhere-swift/Sources/FoundationModelsAdapter/FoundationModelsAdapter.swift (2)
29-43: Registration logic is well-structured.The conditional compilation with
#if canImport(FoundationModels)and runtime availability guards provide proper fallback behavior with informative logging.
86-97: Error handling properly preserves error types.The do-catch correctly re-throws
LLMServiceErroras-is while wrapping other errors withgenerationFailed. This maintains error fidelity through the call chain.examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift (1)
351-355: LGTM! Improved user-facing copy.The updated loading messages use more user-friendly language and emphasize privacy ("private AI assistant"), which enhances the user experience.
| } else { | ||
| // Production Mode - Real API key required | ||
| let apiKey = "testing_api_key" // TODO: Get from secure storage | ||
| let apiKey = "prod_api_key" // Get from secure storage in production |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace hardcoded API key with secure storage.
The placeholder API key "prod_api_key" is hardcoded in the production code path. Even with the comment, this poses a security risk if accidentally shipped. Use iOS Keychain Services to retrieve the API key securely.
🔎 Recommended implementation using Keychain
- let apiKey = "prod_api_key" // Get from secure storage in production
+ // Retrieve API key from Keychain
+ guard let apiKey = KeychainHelper.retrieveAPIKey() else {
+ throw SDKError.missingAPIKey
+ }You'll need to implement a KeychainHelper utility that wraps Security framework APIs to store and retrieve credentials securely.
Committable suggestion skipped: line range outside the PR's diff.
| try! ModelRegistration( | ||
| url: "https://huggingface.co/Triangle104/Qwen2.5-0.5B-Instruct-Q6_K-GGUF/resolve/main/qwen2.5-0.5b-instruct-q6_k.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "qwen-2.5-0.5b-instruct-q6-k", | ||
| name: "Qwen 2.5 0.5B Instruct Q6_K", | ||
| name: "Smart Assistant", | ||
| memoryRequirement: 600_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q4_K_M.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "lfm2-350m-q4-k-m", | ||
| name: "LiquidAI LFM2 350M Q4_K_M", | ||
| memoryRequirement: 250_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q8_0.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "lfm2-350m-q8-0", | ||
| name: "LiquidAI LFM2 350M Q8_0", | ||
| name: "Quality Assistant", | ||
| memoryRequirement: 400_000_000 | ||
| ) | ||
| ] | ||
| ) | ||
| logger.info("✅ LlamaCPP Core registered (runanywhere-core backend)") | ||
|
|
||
| // Register WhisperKit with STT models | ||
| await RunAnywhere.registerFramework( | ||
| WhisperKitAdapter.shared, | ||
| models: [ | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/argmaxinc/whisperkit-coreml/tree/main/openai_whisper-tiny.en", | ||
| framework: .whisperKit, | ||
| modality: .voiceToText, | ||
| id: "whisper-tiny", | ||
| name: "Whisper Tiny", | ||
| format: .mlmodel, | ||
| memoryRequirement: 39_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/argmaxinc/whisperkit-coreml/tree/main/openai_whisper-base", | ||
| framework: .whisperKit, | ||
| modality: .voiceToText, | ||
| id: "whisper-base", | ||
| name: "Whisper Base", | ||
| format: .mlmodel, | ||
| memoryRequirement: 74_000_000 | ||
| ) | ||
| url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q4_K_M.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "lfm2-350m-q4-k-m", | ||
| name: "Balanced Assistant", | ||
| memoryRequirement: 250_000_000 | ||
| ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle ModelRegistration errors gracefully instead of crashing.
Using try! for model registrations will crash the app if any ModelRegistration fails (e.g., malformed URL). During app initialization, this would prevent the app from starting. Consider using try? or proper error handling to skip invalid models and log warnings instead.
🔎 Safer error handling approach
await RunAnywhere.registerFramework(
LlamaCPPCoreAdapter(),
models: [
- try! ModelRegistration(
+ ModelRegistration(
url: "https://huggingface.co/Triangle104/Qwen2.5-0.5B-Instruct-Q6_K-GGUF/resolve/main/qwen2.5-0.5b-instruct-q6_k.gguf",
framework: .llamaCpp,
modality: .textToText,
id: "qwen-2.5-0.5b-instruct-q6-k",
name: "Smart Assistant",
memoryRequirement: 600_000_000
- ),
- try! ModelRegistration(
+ ).map { [$0] } ?? [],
+ ModelRegistration(
url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q8_0.gguf",
framework: .llamaCpp,
modality: .textToText,
id: "lfm2-350m-q8-0",
name: "Quality Assistant",
memoryRequirement: 400_000_000
- ),
- try! ModelRegistration(
+ ).map { [$0] } ?? [],
+ ModelRegistration(
url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q4_K_M.gguf",
framework: .llamaCpp,
modality: .textToText,
id: "lfm2-350m-q4-k-m",
name: "Balanced Assistant",
memoryRequirement: 250_000_000
- ),
- ]
+ ).map { [$0] } ?? []
+ ].flatMap { $0 }
)
+
+ // Log if any models failed to register
+ logger.warning("Some models failed to register but app continues")Or create a helper function:
private func safeModelRegistration(
url: String,
framework: Framework,
modality: Modality,
id: String,
name: String,
format: ModelFormat? = nil,
memoryRequirement: Int64
) -> ModelRegistration? {
do {
return try ModelRegistration(
url: url,
framework: framework,
modality: modality,
id: id,
name: name,
format: format,
memoryRequirement: memoryRequirement
)
} catch {
logger.error("Failed to register model \(name): \(error)")
return nil
}
}Then use models: [safeModelRegistration(...), ...].compactMap { $0 }.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift around
lines 179-202, the ModelRegistration calls use try! which will crash the app on
any registration error; change these to safe, non‑throwing handling by replacing
try! with either try? or a small wrapper that catches errors, logs a warning
(including model id/name and the error), and returns nil so you can compactMap
the registrations to skip invalid entries; ensure the final models array uses
compactMap to exclude failed registrations so app initialization continues
safely.
| // Register LlamaCPP Core with curated LLM models (same as development) | ||
| await RunAnywhere.registerFramework( | ||
| LlamaCPPCoreAdapter(), | ||
| models: [ | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/prithivMLmods/SmolLM2-360M-GGUF/resolve/main/SmolLM2-360M.Q8_0.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "smollm2-360m-q8-0", | ||
| name: "SmolLM2 360M Q8_0", | ||
| memoryRequirement: 500_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q4_K_M.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "llama2-7b-q4-k-m", | ||
| name: "Llama 2 7B Chat Q4_K_M", | ||
| memoryRequirement: 4_000_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF/resolve/main/mistral-7b-instruct-v0.1.Q4_K_M.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "mistral-7b-q4-k-m", | ||
| name: "Mistral 7B Instruct Q4_K_M", | ||
| memoryRequirement: 4_000_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/Triangle104/Qwen2.5-0.5B-Instruct-Q6_K-GGUF/resolve/main/qwen2.5-0.5b-instruct-q6_k.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "qwen-2.5-0.5b-instruct-q6-k", | ||
| name: "Qwen 2.5 0.5B Instruct Q6_K", | ||
| name: "Smart Assistant", | ||
| memoryRequirement: 600_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q4_K_M.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "lfm2-350m-q4-k-m", | ||
| name: "LiquidAI LFM2 350M Q4_K_M", | ||
| memoryRequirement: 250_000_000 | ||
| ), | ||
| try! ModelRegistration( | ||
| url: "https://huggingface.co/LiquidAI/LFM2-350M-GGUF/resolve/main/LFM2-350M-Q8_0.gguf", | ||
| framework: .llamaCpp, | ||
| modality: .textToText, | ||
| id: "lfm2-350m-q8-0", | ||
| name: "LiquidAI LFM2 350M Q8_0", | ||
| name: "Quality Assistant", | ||
| memoryRequirement: 400_000_000 | ||
| ) | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, verify references to the missing "Balanced Assistant" model
rg -n "Balanced Assistant|lfm2-350m-q4-k-m" --type swiftRepository: RunanywhereAI/runanywhere-sdks
Length of output: 442
🏁 Script executed:
# Also examine the actual file to see both development and production sections
cd examples/ios/RunAnywhereAI/RunAnywhereAI/App || cd . && find . -name "RunAnywhereAIApp.swift" -exec wc -l {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 102
🏁 Script executed:
# Read the file to examine the development section (around lines 179-202) and production section (262-282)
find . -name "RunAnywhereAIApp.swift" -exec sed -n '170,290p' {} +Repository: RunanywhereAI/runanywhere-sdks
Length of output: 5520
Fix misleading comment and verify intentional model difference between development and production.
Production's registerAdaptersForProduction() registers only 2 LlamaCPP models ("Smart Assistant" and "Quality Assistant") while registerAdaptersForDevelopment() registers 3, including "Balanced Assistant" (lfm2-350m-q4-k-m with 250MB requirement). The production comment states "(same as development)" which is incorrect. Either add the missing "Balanced Assistant" model to production or update the comment to accurately reflect the intentional difference.
🤖 Prompt for AI Agents
In examples/ios/RunAnywhereAI/RunAnywhereAI/App/RunAnywhereAIApp.swift around
lines 262 to 282, the comment "same as development" is misleading because
production registers only two LlamaCPP models while development registers three
(including "Balanced Assistant"). Either add the missing Balanced Assistant
ModelRegistration (lfm2-350m-q4-k-m, id lfm2-350m-q4-k-m, name "Balanced
Assistant", memoryRequirement 250_000_000) to the production models list, or
change the comment to accurately state that production intentionally registers
only the two models; update code accordingly to keep models consistent with the
chosen intent.
Description
Brief description of the changes made.
Type of Change
Testing
Labels
Please add the appropriate label(s):
iOS SDK- Changes to iOS/Swift SDKAndroid SDK- Changes to Android/Kotlin SDKiOS Sample- Changes to iOS example appAndroid Sample- Changes to Android example appChecklist
Screenshots - Attach all the relevant UI changes screenshots for iOS/Android and MacOS/Tablet/large screen sizes
Important
This PR removes WhisperKit dependencies, enhances ONNX Runtime support, and improves framework availability detection in the iOS example app.
RunAnywhereWhisperKitdependency fromPackage.swiftand project configuration.getAvailableFrameworks()withgetFrameworkAvailability()inModelSelectionSheet.swiftandSimplifiedModelsView.swift.project.pbxproj.ModelSelectionSheet.swift.ModelStatusBannerandModelRequiredOverlayinModelStatusComponents.swiftfor better user feedback.project.pbxproj.Package.resolved.This description was created by
for 2f1b78d. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
Bug Fixes
Chores
✏️ Tip: You can customize this high-level summary in your review settings.
Greptile Overview
Greptile Summary
This PR removes WhisperKit dependencies and improves macOS ONNX Runtime support in the iOS example app. The changes eliminate the
RunAnywhereWhisperKitdependency from Package.swift and project configuration, transitioning the app to rely solely on ONNX-based speech-to-text capabilities. The implementation enhances framework availability detection by replacinggetAvailableFrameworks()withgetFrameworkAvailability(), providing more detailed status information and user feedback when frameworks are unavailable. Additionally, the PR configures macOS library search paths for Homebrew-installed ONNX Runtime libraries and updates the app to version 0.14.0 with a simplified bundle identifier.Important Files Changed
Confidence score: 4/5
Context used:
dashboard- CLAUDE.md (source)