-
Notifications
You must be signed in to change notification settings - Fork 97
React-native alignment with iOS #252
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: smonga/android_rearch
Are you sure you want to change the base?
Conversation
… files - Introduced a new .yarnrc.yml file to set the node linker to node-modules. - Updated yarn.lock to reflect new dependency versions. - Removed obsolete example files: streaming-llm-example.ts and TTSExample.ts, which are no longer needed. - Added new Core and Feature modules for improved functionality and organization. - Refactored various components and services to enhance maintainability and performance.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 WalkthroughWalkthroughThis PR restructures the React Native SDK's architecture by removing deprecated memory management and routing subsystems, introducing a capability-based lifecycle framework with integrated analytics, and establishing network, authentication, and data repository infrastructure for server synchronization. Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
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 |
…and update TypeScript settings - Introduced new linting reports for ESLint and TypeScript, enhancing code quality checks. - Added configuration files for knip and updated TypeScript settings to exclude test files. - Created scripts for checking todos and running analysis, improving development workflow. - Updated package.json and yarn.lock to reflect new dependencies and configurations. - Removed obsolete files and refactored existing services for better organization and maintainability.
…ndling and type safety - Updated MemoryMonitor to handle null entries in recent history and memory entries, enhancing robustness. - Refactored various services to replace 'any' types with more specific types, improving type safety. - Enhanced logging in ManagedLifecycle and ModelLifecycleManager to utilize SDKLogger for consistent logging practices. - Removed obsolete configuration files related to LLM and SpeakerDiarization, streamlining the codebase. - Improved event handling in EventBus to prevent potential runtime errors when accessing subscribers.
…functionality - Added optional peer dependencies: react-native-fs, react-native-blob-util, react-native-device-info, and react-native-zip-archive to support enhanced file and device management. - Refactored HardwareCapabilityManager to utilize react-native-device-info for better device capability detection. - Updated DownloadService to leverage react-native-blob-util and react-native-fs for improved download management and file operations. - Removed obsolete memory management services to streamline the codebase and improve maintainability. - Enhanced STT and TTS capabilities with updated data structures and improved handling of transcription results.
- Removed legacy SDKError exports and restructured error handling to improve clarity and maintainability. - Introduced AuthenticationService for managing device registration and token management, aligning with iOS SDK functionality. - Added DeviceRegistrationService for handling device registration with backend, including fallback storage options. - Implemented ModelAssignmentService for fetching and managing model assignments from the backend, enhancing model management capabilities. - Updated logging infrastructure to support centralized logging with multiple destinations. - Refactored LLM capabilities to include generation metrics and analytics tracking for improved performance insights. - Streamlined the ServiceContainer to manage new services and dependencies effectively.
…structure - Deleted LoadedModel, ModelLoadingService, ExecutionTarget, RoutingDecision, RoutingReason, CostCalculator, ResourceChecker, RoutingService, GenerationOptionsResolver, GenerationService, StreamingService, ThinkingParser, TokenCounter, and related files to enhance maintainability. - Refactored imports and dependencies across the SDK to reflect the removal of these services. - Improved overall code organization by eliminating unused components and consolidating functionality.
- Added structured output generation features, including Generatable protocol and JSON schema utilities for LLM responses. - Introduced new data protocols and repositories for improved data management, including DataSource and RepositoryEntity. - Implemented error handling for STT and TTS operations, enhancing robustness with typed error classes. - Refactored existing modules to streamline imports and improve organization, ensuring better maintainability. - Updated enums to include new audio formats and associated utility functions for file handling.
- Introduced Voice Session module for high-level voice assistant integration, including event handling and configuration options. - Added Speaker Diarization error handling with specific error codes and classes for improved robustness. - Updated SDK structure to include new VoiceSession and SpeakerDiarization features, enhancing overall functionality. - Refactored existing imports to streamline access to new modules and improve organization.
|
@coderabbitai please do a detailed review |
|
@greptile please do a detailed review |
|
@sanchitmonga22: I'll perform a detailed review of the changes in this PR. ✅ Actions performedReview triggered.
|
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.
286 files reviewed, 4 comments
| setTimeout(async () => { | ||
| try { | ||
| await this.completeServicesInitialization(); | ||
| logger.info('Phase 2 complete (background)'); | ||
| } catch (error) { | ||
| // Phase 2 failure is non-critical | ||
| const errorMessage = | ||
| error instanceof Error ? error.message : String(error); | ||
| logger.warning(`Phase 2 failed (non-critical): ${errorMessage}`); | ||
| } | ||
| }, 0); |
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.
logic: using setTimeout(..., 0) to defer Phase 2 makes error handling non-deterministic. If Phase 2 fails, the error is only logged but never surfaces to the caller. This creates a silent failure mode where areServicesReady stays false indefinitely.
consider returning a Promise that tracks Phase 2 completion, allowing callers to optionally await it if they need guarantees about service readiness.
Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-react-native/src/Public/RunAnywhere.ts
Line: 530:540
Comment:
**logic:** using `setTimeout(..., 0)` to defer Phase 2 makes error handling non-deterministic. If Phase 2 fails, the error is only logged but never surfaces to the caller. This creates a silent failure mode where `areServicesReady` stays false indefinitely.
consider returning a Promise that tracks Phase 2 completion, allowing callers to optionally await it if they need guarantees about service readiness.
How can I resolve this? If you propose a fix, please make it concise.| appVersion: '1.0.0', // TODO: Get from app config | ||
| sdkVersion: '0.1.0', // TODO: Get from SDK version |
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.
logic: hardcoded version values will cause analytics/telemetry data to be inaccurate
Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-react-native/src/Infrastructure/Device/Services/DeviceRegistrationService.ts
Line: 239:240
Comment:
**logic:** hardcoded version values will cause analytics/telemetry data to be inaccurate
How can I resolve this? If you propose a fix, please make it concise.| const { requireDeviceInfoModule } = await import('../../../native'); | ||
| const deviceInfo = requireDeviceInfoModule(); | ||
| platform = (await deviceInfo.getPlatform?.()) ?? 'ios'; | ||
| deviceType = 'phone'; // TODO: Detect phone vs tablet |
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.
logic: defaulting all devices to 'phone' will cause incorrect model assignments for tablet devices with more capable hardware
Prompt To Fix With AI
This is a comment left during a code review.
Path: sdk/runanywhere-react-native/src/Infrastructure/ModelManagement/Services/ModelAssignmentService.ts
Line: 201:201
Comment:
**logic:** defaulting all devices to 'phone' will cause incorrect model assignments for tablet devices with more capable hardware
How can I resolve this? If you propose a fix, please make it concise.| api_key: apiKey, | ||
| device_id: deviceId, | ||
| platform: 'react-native', | ||
| sdk_version: '0.1.0', // TODO: Get from version file |
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.
style: hardcoded SDK version should be imported from SDKConstants.version
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: sdk/runanywhere-react-native/src/Data/Network/Services/AuthenticationService.ts
Line: 157:157
Comment:
**style:** hardcoded SDK version should be imported from `SDKConstants.version`
<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.- Removed unused error exports and consolidated error handling for STT, TTS, and VAD features to improve clarity and maintainability. - Updated import statements for better organization and consistency across modules. - Enhanced error classes with improved formatting for better readability. - Deleted obsolete files related to error handling to streamline the codebase.
|
@coderabbitai please do a full review of the PR |
|
@sanchitmonga22: I'll perform a full review of all the changes in this PR. ✅ Actions performedFull review triggered. |
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: 14
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
sdk/runanywhere-react-native/src/Core/Models/Common/SDKComponent.ts (1)
39-51: Non-exhaustive switch causes undefined return for VLM and WakeWord.The
componentRequiresModelfunction has the same issue asgetComponentDisplayName: it no longer handlesSDKComponent.VLMandSDKComponent.WakeWord, returningundefinedinstead of a boolean. This can cause logical errors in conditionals where a boolean is expected.🔎 Proposed fix: Add explicit handling or default case
export function componentRequiresModel(component: SDKComponent): boolean { switch (component) { case SDKComponent.LLM: case SDKComponent.STT: case SDKComponent.Embedding: return true; case SDKComponent.TTS: case SDKComponent.VAD: case SDKComponent.SpeakerDiarization: case SDKComponent.VoiceAgent: return false; + case SDKComponent.VLM: + case SDKComponent.WakeWord: + return false; // or true, depending on whether these components require models } }Alternatively, add a
defaultcase that returnsfalseor throws an error for unsupported components.sdk/runanywhere-react-native/src/Capabilities/Registry/Services/RegistryService.ts (1)
82-98:registerModelPersistentlydoesn't actually persist.The persistence logic is entirely commented out, making this method functionally identical to
registerModel. Either implement the persistence or remove this method to avoid misleading API consumers.
♻️ Duplicate comments (1)
sdk/runanywhere-react-native/src/Data/Network/Services/AuthenticationService.ts (1)
153-158: Hardcoded SDK version should useSDKConstants.version.This issue was already flagged in a previous review. The
sdk_versionshould be imported fromSDKConstants.versioninstead of being hardcoded.
🟡 Minor comments (7)
sdk/runanywhere-react-native/src/Core/Models/STT/STTTranscriptionResult.ts-34-45 (1)
34-45: Document confidence range.The
confidencefield should document its expected range for consistency with the other interfaces (0.0-1.0).🔎 Suggested documentation enhancement
export interface STTTranscriptionResult { /** The transcribed text */ transcript: string; - /** Confidence score for the transcription (optional) */ + /** Confidence score for the transcription, range 0.0-1.0 (optional) */ confidence?: number; /** Word-level timestamp information (optional) */ timestamps?: TimestampInfo[]; /** Detected language (optional) */ language?: string; /** Alternative transcriptions (optional) */ alternatives?: AlternativeTranscription[]; }sdk/runanywhere-react-native/scripts/run_analysis.js-34-42 (1)
34-42: Missing stderr capture on command failure.When
execSyncthrows, error messages may be inerror.stderrrather thanerror.stdout. The current code only captureserror.stdout || error.message, potentially losing diagnostic output.🔎 Proposed fix
} catch (error) { - const output = error.stdout || error.message; + const output = [error.stdout, error.stderr, error.message] + .filter(Boolean) + .join('\n'); fs.writeFileSync(outputFile, output);sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Services/HardwareCapabilityManager.ts-432-442 (1)
432-442: Unreliable Android NPU detection.Checking for chipset names in the model string is unreliable:
- Many devices don't include chipset names in their model identifier
- Not all Snapdragon/Exynos chips have NPUs (older generations lack them)
- A Samsung "Galaxy S23" won't have "Snapdragon" or "Exynos" in its model name
Consider defaulting Android NPU to
falseor using a known-device lookup table for high-confidence detection.🔎 Proposed conservative approach
if (Platform.OS === 'android') { - // Check for known NPU-capable chips - const deviceLower = (model + deviceId).toLowerCase(); - return ( - deviceLower.includes('snapdragon') || - deviceLower.includes('exynos') || - deviceLower.includes('tensor') || - deviceLower.includes('dimensity') || - deviceLower.includes('kirin') - ); + // NPU detection on Android is unreliable without native APIs + // Default to false; GPU acceleration is still available + return false; }sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Services/HardwareCapabilityManager.ts-67-95 (1)
67-95: Inconsistent fallback values for device identifier.The sync getter returns
'Unknown-ReactNative'when_deviceIdentifieris null (line 68), butfetchDeviceIdentifiersets${Platform.OS}-Unknownwhen DeviceInfo is unavailable (line 89). This inconsistency could cause unexpected behavior if code compares identifiers.🔎 Proposed fix
} else { - this._deviceIdentifier = `${Platform.OS}-Unknown`; + this._deviceIdentifier = 'Unknown-ReactNative'; }Or update the sync getter to match:
public get deviceIdentifier(): string { - return this._deviceIdentifier ?? 'Unknown-ReactNative'; + return this._deviceIdentifier ?? `${Platform.OS}-Unknown`; }sdk/runanywhere-react-native/src/Capabilities/Registry/Services/RegistryService.ts-32-32 (1)
32-32: Unused_apiKeyparameter.The
initializemethod accepts_apiKeybut never uses it. If the API key is needed for model discovery or remote fetching, it should be utilized; otherwise, consider removing the parameter.sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts-137-145 (1)
137-145:loadingState('')passes empty string instead of the resourceId being loaded.When a load is in progress,
loadingState('')should ideally pass the resourceId currently being loaded. However, sinceinflightPromisedoesn't track which resource is being loaded, you may need to add a field likeloadingResourceIdto track this.🔎 Suggested approach
private service: TService | null = null; private loadedResourceId: string | null = null; + private loadingResourceId: string | null = null; private inflightPromise: Promise<TService> | null = null;Then update the
stategetter andloadmethod accordingly.Committable suggestion skipped: line range outside the PR's diff.
sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/StructuredOutputHandler.ts-312-326 (1)
312-326: Unusedschemaparameter inparseStructuredOutputThe
schema: GeneratableTypeparameter is accepted but never used for validation. The method only extracts and parses JSON without validating against the provided schema. This could lead to runtime errors if the parsed JSON doesn't conform to the expected typeT.Consider either:
- Implementing actual schema validation using the
jsonSchemaproperty- Removing the unused parameter and documenting that validation is the caller's responsibility
🔎 If validation is intended to be caller's responsibility
- public parseStructuredOutput<T>(text: string, schema: GeneratableType): T { + /** + * Parse JSON from generated text. Note: Does not validate against schema. + * Caller should validate the returned object matches expected type. + */ + public parseStructuredOutput<T>(text: string, _schema?: GeneratableType): T {
🧹 Nitpick comments (29)
sdk/runanywhere-react-native/src/Core/Models/TTS/TTSResult.ts (1)
60-63: Base64 size approximation ignores padding characters.The
* 0.75factor doesn't account for base64 padding (=characters), which can cause the result to be slightly over-estimated (by up to 2 bytes). This is likely acceptable for most use cases, but if precision matters, consider accounting for padding.🔎 More accurate calculation
export function getTTSResultAudioSizeBytes(result: TTSResult): number { - // Base64 to raw bytes: base64 length * 3/4 - return Math.floor(result.audioData.length * 0.75); + // Base64 to raw bytes, accounting for padding + const padding = (result.audioData.match(/=$/g) || []).length; + return Math.floor((result.audioData.length * 3) / 4) - padding; }sdk/runanywhere-react-native/src/Core/Models/STT/STTTranscriptionResult.ts (2)
9-18: Document confidence score range and consider time validation.The
confidencefield lacks documentation about its expected range (e.g., 0.0-1.0). Additionally, there's no indication thatstartTimeshould be less thanendTime, which could lead to invalid data if not validated upstream.🔎 Suggested documentation enhancement
export interface TimestampInfo { /** The word */ word: string; /** Start time in seconds */ startTime: number; /** End time in seconds */ endTime: number; - /** Confidence score for this word (optional) */ + /** Confidence score for this word, range 0.0-1.0 (optional) */ confidence?: number; }
23-28: Document confidence score range.Similar to
TimestampInfo, theconfidencefield should document its expected range (e.g., 0.0-1.0 or 0-100).🔎 Suggested documentation enhancement
export interface AlternativeTranscription { /** The alternative transcript text */ transcript: string; - /** Confidence score for this alternative */ + /** Confidence score for this alternative, range 0.0-1.0 */ confidence: number; }sdk/runanywhere-react-native/src/Features/LLM/Errors/LLMError.ts (1)
162-167: ErrorCode.GenerationFailed is semantically inaccurate for service busy state.The
serviceBusy()method usesErrorCode.GenerationFailed, which conflates "the service is currently processing another request" with "generation failed." No more appropriate error code exists in the enum. Consider adding a new error code (e.g.,ErrorCode.ServiceBusyorErrorCode.ServiceUnavailable) to the ErrorCode enum to better represent transient service unavailability.sdk/runanywhere-react-native/knip.json (1)
6-20: Duplicate test exclusion patterns.Test patterns are excluded in both
project(lines 8-9) andignore(lines 19-20). While this doesn't cause issues, it's redundant since exclusions inprojectalready prevent those files from being analyzed.🔎 Proposed simplification
"ignore": [ "lib/**", "nitrogen/**", "node_modules/**", "android/**", "ios/**", "cpp/**", - "example/**", - "src/__tests__/**", - "src/**/*.test.ts" + "example/**" ],sdk/runanywhere-react-native/scripts/check_todos.js (1)
16-21: Redundant skip logic and misleading naming.
SKIP_DIRSincludes.test.tswhich is a file extension, not a directory (misleading name). Additionally,glob.syncat lines 50-51 already excludes these patterns viaignore, making theshouldSkipcheck at line 57 redundant.🔎 Proposed simplification
Remove the redundant skip logic since glob already handles filtering:
-// Directories to skip -const SKIP_DIRS = ['node_modules', '__tests__', '.test.ts']; - -function shouldSkip(filePath) { - return SKIP_DIRS.some(skip => filePath.includes(skip)); -} - function checkFile(filePath) {files.forEach(file => { - if (!shouldSkip(file)) { - const issues = checkFile(file); - allIssues = allIssues.concat(issues); - } + const issues = checkFile(file); + allIssues = allIssues.concat(issues); });sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Services/HardwareCapabilityManager.ts (2)
222-247: Consider model-aware acceleration selection.The
_modelparameter is currently unused. For a more robust implementation, consider usingModelInfoproperties (e.g.,compatibleFrameworks,format) to select appropriate acceleration. Some model formats may not benefit from NPU acceleration.
333-352: Consider extracting magic numbers to named constants.The hardcoded memory values (4GB, 2GB) could be extracted to named constants for better readability and maintainability:
private static readonly DEFAULT_TOTAL_MEMORY = 4_000_000_000; private static readonly DEFAULT_AVAILABLE_MEMORY = 2_000_000_000;sdk/runanywhere-react-native/src/Data/Protocols/RepositoryError.ts (2)
93-108: Duplicate method implementation.The methods
networkUnavailable()andnetworkNotAvailable()have identical implementations. Consider one of these approaches:
- If both are needed for backwards compatibility, document this and have one delegate to the other
- If this is unintentional duplication, remove one method
🔎 Proposed fix to eliminate duplication
/** * Network unavailable for sync */ static networkUnavailable(): RepositoryError { return new RepositoryError( ErrorCode.NetworkUnavailable, 'Network unavailable for sync' ); } /** * Network not available (alias) */ static networkNotAvailable(): RepositoryError { - return new RepositoryError( - ErrorCode.NetworkUnavailable, - 'Network unavailable for sync' - ); + return this.networkUnavailable(); }
18-65: Consider more specific error codes for distinct operations.The
saveFailure,fetchFailure,deleteFailure, andsyncFailuremethods all useErrorCode.Unknown. If more specific error codes are available in theErrorCodeenum (e.g.,DatabaseWriteError,DatabaseReadError), consider using them to improve error diagnostics and handling.sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts (1)
260-268: Inefficient logger instantiation on every log call.Creating a new
SDKLoggerinstance on eachlog()andlogError()call is wasteful. Consider making the logger a class field initialized once in the constructor.🔎 Proposed fix
// MARK: - Dependencies private readonly category: string; + private readonly logger: SDKLogger; private readonly loadResourceFn: LoadResourceFn<TService>; private readonly unloadResourceFn: UnloadResourceFn<TService>; // MARK: - Initialization constructor(options: ModelLifecycleManagerOptions<TService>) { this.category = options.category; + this.logger = new SDKLogger(options.category); this.loadResourceFn = options.loadResource; this.unloadResourceFn = options.unloadResource; } // ... private log(message: string): void { - const logger = new SDKLogger(this.category); - logger.debug(message); + this.logger.debug(message); } private logError(message: string): void { - const logger = new SDKLogger(this.category); - logger.error(message); + this.logger.error(message); }sdk/runanywhere-react-native/src/Data/Network/Services/APIClient.ts (1)
277-292: Duplicate error handling logic inpostRawandgetRaw.The catch block logic (lines 277-292 and 327-342) is nearly identical. Consider extracting to a private helper method.
🔎 Suggested extraction
private handleFetchError(error: unknown): never { if (error instanceof APIClientError) { throw error; } if ((error as Error).name === 'AbortError') { throw new APIClientError('Request timeout', 0); } throw new APIClientError( (error as Error).message ?? 'Network request failed', 0 ); }Also applies to: 327-342
sdk/runanywhere-react-native/src/Core/Capabilities/ManagedLifecycle.ts (2)
483-507: Misleading comment increateModelEvent.The comment says "Reuse generic model events for VAD/Diarization" but VAD and Diarization have their own dedicated event creators handled in
createVADEventandcreateSpeakerDiarizationEventabove. This fallback is for unknown/future resource types.🔎 Suggested comment fix
private createModelEvent( type: LifecycleEventType, resourceId: string, durationMs?: number, error?: Error ): SDKEvent { - // Reuse generic model events for VAD/Diarization + // Fallback to generic model events for unknown resource types switch (type) {
511-519: Same inefficient logger pattern asModelLifecycleManager.Consider making the logger a class field to avoid repeated instantiation, consistent with the suggested refactor in
ModelLifecycleManager.ts.sdk/runanywhere-react-native/src/Data/Protocols/DataSource.ts (1)
182-196: Timeout race leaks timers and doesn't abort the operation.When the operation completes first, the
setTimeouttimer continues running until it fires. Additionally, if the timeout fires first, the underlying operation continues executing in the background.Consider clearing the timer on completion and optionally supporting
AbortSignalfor cancellable operations.🔎 Proposed fix with timer cleanup
export class RemoteOperationHelper { constructor(private readonly timeout: number = 10000) {} async withTimeout<R>(operation: () => Promise<R>): Promise<R> { - return Promise.race([ - operation(), - new Promise<R>((_, reject) => - setTimeout( - () => reject(DataSourceError.networkUnavailable()), - this.timeout - ) - ), - ]); + let timeoutId: ReturnType<typeof setTimeout>; + const timeoutPromise = new Promise<R>((_, reject) => { + timeoutId = setTimeout( + () => reject(DataSourceError.networkUnavailable()), + this.timeout + ); + }); + try { + return await Promise.race([operation(), timeoutPromise]); + } finally { + clearTimeout(timeoutId!); + } } }sdk/runanywhere-react-native/src/Features/LLM/LLMCapability.ts (3)
508-510: Unused variable_modelId.The variable is assigned but never used in
generateStreamWithMetrics.🔎 Proposed fix
// Use managedLifecycle.requireService() for iOS parity const llmService = this.managedLifecycle.requireService(); - const _modelId = this.managedLifecycle.resourceIdOrUnknown();
726-739: Unused variable_performanceMetrics.
PerformanceMetricsImplis instantiated but never used or returned. If this is intentional scaffolding for future use, consider adding a TODO comment; otherwise, remove it.🔎 Proposed fix (remove if unused)
// Estimate prompt tokens (rough estimate: 1 token ≈ 4 characters) const promptTokens = Math.floor(collector.fullText.length / 4); const completionTokens = collector.tokenCount; - const _performanceMetrics = new PerformanceMetricsImpl({ - tokenizationTimeMs: 0, - inferenceTimeMs: totalTimeMs, - postProcessingTimeMs: 0, - tokensPerSecond, - peakMemoryUsage: 0, - queueWaitTimeMs: 0, - timeToFirstTokenMs, - thinkingTimeMs: null, - responseTimeMs: totalTimeMs, - }); - return {
666-670: Simplify optional chaining with nullish check.The
shift()can returnundefinedon an empty array. Thecontinuehandles this correctly, but it's slightly more idiomatic to use a single guard.🔎 Minor simplification
if (tokenQueue.length > 0) { - const token = tokenQueue.shift(); - if (!token) continue; + const token = tokenQueue.shift()!; yield token;This is safe because the
length > 0check guarantees a value exists.sdk/runanywhere-react-native/src/Core/Capabilities/ResourceTypes.ts (1)
29-46: Consider leveraging TypeScript exhaustiveness checking.The implementation is correct, but you could make the switch statement exhaustive to catch missing cases at compile time if new enum members are added later.
🔎 Optional improvement for exhaustiveness
export function getResourceTypeDisplayName( type: CapabilityResourceType ): string { switch (type) { case CapabilityResourceType.LLMModel: return 'LLM Model'; case CapabilityResourceType.STTModel: return 'STT Model'; case CapabilityResourceType.TTSVoice: return 'TTS Voice'; case CapabilityResourceType.VADModel: return 'VAD Model'; case CapabilityResourceType.DiarizationModel: return 'Diarization Model'; default: - return 'Unknown Resource'; + const _exhaustive: never = type; + return _exhaustive; } }This pattern ensures that if a new enum member is added without updating the switch, TypeScript will emit a compile error.
sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/StructuredOutputHandler.ts (2)
14-19: Duplicate type definition:GeneratableTypevsGeneratableThis interface duplicates the
Generatableinterface defined insdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/Generatable.ts(lines 31-41 in relevant snippets showStructuredOutputConfigusingGeneratable). This creates two parallel type hierarchies for the same concept.Consider consolidating these into a single type and re-exporting from a central location to avoid divergence.
332-350: Unused_configparameter invalidateStructuredOutputThe
_configparameter is marked as unused (underscore prefix) but the method could useconfig.type.jsonSchemato perform actual schema validation instead of just checking if JSON is extractable.sdk/runanywhere-react-native/src/Data/Protocols/Repository.ts (1)
84-98: Sequential processing inmarkSyncedmay be slow for large batchesThe current implementation processes each ID sequentially with individual
fetchandsavecalls. For large sync batches, this could be slow due to the round-trip overhead of each operation.Additionally, if one operation fails, the remaining entities won't be processed, leaving partial state.
🔎 Consider parallel processing with error collection
async markSynced<Entity extends RepositoryEntity>( repository: Repository<Entity>, ids: string[] ): Promise<void> { - for (const id of ids) { - const entity = await repository.fetch(id); - if (entity) { - const updated = { - ...entity, - syncPending: false, - }; - await repository.save(updated); - } - } + await Promise.all( + ids.map(async (id) => { + const entity = await repository.fetch(id); + if (entity) { + await repository.save({ ...entity, syncPending: false }); + } + }) + ); },sdk/runanywhere-react-native/src/Data/Network/Services/NetworkService.ts (1)
124-130: Generic error message loses response detailsThe error only includes
response.statusTextbut not the status code or response body, making debugging difficult. Consider including more context.🔎 Include status code in error
if (!response.ok) { - throw new Error(`Network request failed: ${response.statusText}`); + throw new Error(`Network request failed: ${response.status} ${response.statusText}`); }sdk/runanywhere-react-native/src/Data/Network/Models/AuthModels.ts (1)
166-177: Hardcoded SDK version should useSDKConstants.version.The default
sdkVersionparameter is hardcoded as'0.1.0'. This should import and useSDKConstants.versionto ensure consistency across the codebase and avoid drift when the version is updated.Proposed fix
+import { SDKConstants } from '../../../Foundation/Constants/SDKConstants'; + export function createAuthRequest( apiKey: string, deviceId: string, - sdkVersion: string = '0.1.0' + sdkVersion: string = SDKConstants.version ): AuthenticationRequest {sdk/runanywhere-react-native/src/Data/Network/Services/AuthenticationService.ts (2)
75-75: Incomplete singleton pattern -_instanceis never assigned.The static
_instancefield is declared andreset()clears it, butcreateAndAuthenticate()never assigns the created instance to_instance. Either complete the singleton pattern or remove the unused field andreset()method.Option 1: Complete the singleton pattern
static async createAndAuthenticate( apiClient: APIClient, apiKey: string, environment: SDKEnvironment ): Promise<AuthenticationService> { const authService = new AuthenticationService(apiClient, environment); + AuthenticationService._instance = authService; // Wire up auth provider to API client apiClient.setAuthenticationProvider(authService);Option 2: Remove unused singleton scaffolding
- private static _instance: AuthenticationService | null = null; // ... at end of class ... - /** - * Reset the singleton (for testing) - */ - static reset(): void { - AuthenticationService._instance = null; - }Also applies to: 398-400
254-261: Add validation for parsed timestamp to guard against corrupted storage.If
expiresAtcontains an invalid value,parseIntreturnsNaN, andnew Date(NaN)produces an invalid date. Consider adding a validation check.Proposed fix
- tokenExpiresAt: expiresAt ? new Date(parseInt(expiresAt, 10)) : null, + tokenExpiresAt: expiresAt + ? (() => { + const ts = parseInt(expiresAt, 10); + return Number.isNaN(ts) ? null : new Date(ts); + })() + : null,sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts (1)
265-327: Consider preserving the underlying error in the error chain.The static factory methods accept an
underlyingErrorparameter but only include its message in the error string. For better debugging, consider setting thecauseproperty (ES2022+) or storing the underlying error as a class property.Proposed enhancement
export class CapabilityError extends Error { + public readonly underlyingError?: Error; + constructor( message: string, - public readonly code: CapabilityErrorCode + public readonly code: CapabilityErrorCode, + underlyingError?: Error ) { super(message); this.name = 'CapabilityError'; + this.underlyingError = underlyingError; + if (underlyingError) { + this.cause = underlyingError; + } } static loadFailed( resource: string, underlyingError?: Error ): CapabilityError { const message = underlyingError ? `Failed to load ${resource}: ${underlyingError.message}` : `Failed to load ${resource}: Unknown error`; - return new CapabilityError(message, CapabilityErrorCode.LoadFailed); + return new CapabilityError(message, CapabilityErrorCode.LoadFailed, underlyingError); }Apply similar changes to
operationFailedandcompositeComponentFailed.sdk/runanywhere-react-native/src/Core/Capabilities/LifecycleEvents.ts (2)
57-65: Consider accepting Error objects to preserve metadata.The
errorparameter is typed asstring, which loses stack traces and structured error information. Consider acceptingError | stringto preserve debugging context while maintaining backward compatibility with string error messages.🔎 Proposed enhancement
export function createLLMModelLoadFailedEvent( modelId: string, - error: string + error: string | Error ): SDKEvent { return createSDKEvent('llm_model_load_failed', EventCategory.LLM, { model_id: modelId, - error, + error: error instanceof Error ? error.message : error, + error_stack: error instanceof Error ? error.stack : undefined, }); }Apply similar changes to STT, TTS, VAD, and SpeakerDiarization load failed event creators.
35-39: Consider adding input validation guards.The event creator functions don't validate inputs. While these are internal SDK functions, adding defensive checks could prevent issues:
- Empty
modelId/voiceIdstrings- Negative
durationMsvalues🔎 Example validation pattern
export function createLLMModelLoadCompletedEvent( modelId: string, durationMs: number ): SDKEvent { + if (!modelId.trim()) { + throw new Error('modelId cannot be empty'); + } + if (durationMs < 0) { + throw new Error('durationMs cannot be negative'); + } return createSDKEvent('llm_model_load_completed', EventCategory.LLM, { model_id: modelId, duration_ms: durationMs.toFixed(1), }); }Apply similar validation to other event creators as needed.
Also applies to: 44-52
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
sdk/runanywhere-react-native/yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (107)
sdk/runanywhere-react-native/.yarnrc.yml(1 hunks)sdk/runanywhere-react-native/examples/TTSExample.tsx(0 hunks)sdk/runanywhere-react-native/examples/streaming-llm-example.ts(0 hunks)sdk/runanywhere-react-native/knip.json(1 hunks)sdk/runanywhere-react-native/package.json(5 hunks)sdk/runanywhere-react-native/scripts/check_todos.js(1 hunks)sdk/runanywhere-react-native/scripts/run_analysis.js(1 hunks)sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Models/DeviceCapabilities.ts(1 hunks)sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Services/HardwareCapabilityManager.ts(5 hunks)sdk/runanywhere-react-native/src/Capabilities/Memory/Services/AllocationManager.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Memory/Services/CacheEviction.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Memory/Services/MemoryMonitor.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Memory/Services/MemoryService.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Memory/Services/PressureHandler.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/ModelLoading/Models/LoadedModel.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/ModelLoading/Services/ModelLoadingService.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Registry/Services/RegistryService.ts(2 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Models/ExecutionTarget.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Models/RoutingDecision.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Models/RoutingReason.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Services/CostCalculator.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Services/ResourceChecker.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/Routing/Services/RoutingService.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/StructuredOutputHandler.ts(4 hunks)sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/index.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationOptions.ts(2 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationResult.ts(1 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/InferenceRequest.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/PerformanceMetrics.ts(1 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/index.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/GenerationOptionsResolver.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/GenerationService.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/StreamingService.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/ThinkingParser.ts(0 hunks)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/TokenCounter.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/Analytics/CoreAnalyticsTypes.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/Analytics/index.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/LifecycleEvents.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/ManagedLifecycle.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/ResourceTypes.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Capabilities/index.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Components/BaseComponent.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Models/Common/RequestPriority.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Common/ResourceAvailability.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Models/Common/SDKComponent.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Models/Common/TelemetryEventType.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/LLMConfiguration.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/STTConfiguration.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/SpeakerDiarizationConfiguration.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/TTSConfiguration.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/VLMConfiguration.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Configuration/WakeWordConfiguration.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/Framework/FrameworkModality.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Models/Framework/LLMFramework.ts(4 hunks)sdk/runanywhere-react-native/src/Core/Models/Model/ModelCategory.ts(4 hunks)sdk/runanywhere-react-native/src/Core/Models/Model/ModelFormat.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Models/Model/ModelInfo.ts(3 hunks)sdk/runanywhere-react-native/src/Core/Models/Model/ModelInfoMetadata.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Models/Model/index.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Models/STT/STTTranscriptionResult.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Models/TTS/TTSResult.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Models/VLM/VLMResult.ts(0 hunks)sdk/runanywhere-react-native/src/Core/ModuleRegistry.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Component/Component.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/LLM/LLMService.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/LLM/LLMServiceProvider.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Lifecycle/ModelLifecycleProtocol.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Memory/MemoryManager.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Memory/MemoryModels.ts(2 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Registry/ModelRegistry.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/VLM/VLMService.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/VLM/VLMServiceProvider.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/STTService.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/STTServiceProvider.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/SpeakerDiarizationService.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/SpeakerDiarizationServiceProvider.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/TTSService.ts(1 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/WakeWordService.ts(0 hunks)sdk/runanywhere-react-native/src/Core/Protocols/Voice/WakeWordServiceProvider.ts(0 hunks)sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadProgress.ts(0 hunks)sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadState.ts(0 hunks)sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadTask.ts(0 hunks)sdk/runanywhere-react-native/src/Data/Network/APIEndpoint.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Network/Models/AuthModels.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Network/Services/APIClient.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Network/Services/AuthenticationService.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Network/Services/DownloadService.ts(0 hunks)sdk/runanywhere-react-native/src/Data/Network/Services/NetworkService.ts(5 hunks)sdk/runanywhere-react-native/src/Data/Network/index.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Protocols/DataSource.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Protocols/Repository.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Protocols/RepositoryEntity.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Protocols/RepositoryError.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Protocols/index.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Repositories/ModelInfoRepository.ts(2 hunks)sdk/runanywhere-react-native/src/Data/Repositories/index.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Services/ModelInfoService.ts(4 hunks)sdk/runanywhere-react-native/src/Data/Services/index.ts(1 hunks)sdk/runanywhere-react-native/src/Data/Sync/SyncCoordinator.ts(5 hunks)sdk/runanywhere-react-native/src/Data/Sync/index.ts(1 hunks)sdk/runanywhere-react-native/src/Data/modelCatalog.ts(5 hunks)sdk/runanywhere-react-native/src/Features/LLM/Errors/LLMError.ts(1 hunks)sdk/runanywhere-react-native/src/Features/LLM/LLMCapability.ts(25 hunks)sdk/runanywhere-react-native/src/Features/LLM/LLMConfiguration.ts(3 hunks)sdk/runanywhere-react-native/src/Features/LLM/LLMModels.ts(1 hunks)
⛔ Files not processed due to max files limit (52)
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/Generatable.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/GenerationHints.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/JSONSchemaGenerator.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/README.md
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StreamAccumulator.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StreamToken.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StructuredOutputGenerationService.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StructuredOutputValidation.ts
- sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/index.ts
- sdk/runanywhere-react-native/src/Features/LLM/index.ts
- sdk/runanywhere-react-native/src/Features/STT/Errors/STTError.ts
- sdk/runanywhere-react-native/src/Features/STT/STTCapability.ts
- sdk/runanywhere-react-native/src/Features/STT/STTConfiguration.ts
- sdk/runanywhere-react-native/src/Features/STT/STTModels.ts
- sdk/runanywhere-react-native/src/Features/STT/index.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/Errors/SpeakerDiarizationError.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/Errors/index.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/SpeakerDiarizationCapability.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/SpeakerDiarizationConfiguration.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/SpeakerDiarizationModels.ts
- sdk/runanywhere-react-native/src/Features/SpeakerDiarization/index.ts
- sdk/runanywhere-react-native/src/Features/TTS/Errors/TTSError.ts
- sdk/runanywhere-react-native/src/Features/TTS/TTSCapability.ts
- sdk/runanywhere-react-native/src/Features/TTS/TTSConfiguration.ts
- sdk/runanywhere-react-native/src/Features/TTS/TTSModels.ts
- sdk/runanywhere-react-native/src/Features/TTS/index.ts
- sdk/runanywhere-react-native/src/Features/VAD/Errors/VADError.ts
- sdk/runanywhere-react-native/src/Features/VAD/VADCapability.ts
- sdk/runanywhere-react-native/src/Features/VAD/VADConfiguration.ts
- sdk/runanywhere-react-native/src/Features/VAD/index.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/Models/AudioPipelineState.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/Models/index.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/VoiceAgentCapability.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/VoiceAgentConfiguration.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/VoiceAgentModels.ts
- sdk/runanywhere-react-native/src/Features/VoiceAgent/index.ts
- sdk/runanywhere-react-native/src/Features/VoiceSession/VoiceSessionConfig.ts
- sdk/runanywhere-react-native/src/Features/VoiceSession/VoiceSessionError.ts
- sdk/runanywhere-react-native/src/Features/VoiceSession/VoiceSessionEvent.ts
- sdk/runanywhere-react-native/src/Features/VoiceSession/VoiceSessionHandle.ts
- sdk/runanywhere-react-native/src/Features/VoiceSession/index.ts
- sdk/runanywhere-react-native/src/Features/index.ts
- sdk/runanywhere-react-native/src/Foundation/Analytics/AnalyticsQueueManager.ts
- sdk/runanywhere-react-native/src/Foundation/Configuration/ConfigurationService.ts
- sdk/runanywhere-react-native/src/Foundation/Constants/SDKConstants.ts
- sdk/runanywhere-react-native/src/Foundation/DependencyInjection/AdapterRegistry.ts
- sdk/runanywhere-react-native/src/Foundation/DependencyInjection/ServiceContainer.ts
- sdk/runanywhere-react-native/src/Foundation/DependencyInjection/ServiceRegistry.ts
- sdk/runanywhere-react-native/src/Foundation/DependencyInjection/index.ts
- sdk/runanywhere-react-native/src/Foundation/DeviceIdentity/DeviceIdentityService.ts
- sdk/runanywhere-react-native/src/Foundation/ErrorTypes/ErrorCategory.ts
- sdk/runanywhere-react-native/src/Foundation/ErrorTypes/ErrorCodes.ts
💤 Files with no reviewable changes (44)
- sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadProgress.ts
- sdk/runanywhere-react-native/src/Core/Models/VLM/VLMResult.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/TokenCounter.ts
- sdk/runanywhere-react-native/src/Core/Models/Configuration/STTConfiguration.ts
- sdk/runanywhere-react-native/src/Capabilities/ModelLoading/Models/LoadedModel.ts
- sdk/runanywhere-react-native/src/Core/Protocols/VLM/VLMService.ts
- sdk/runanywhere-react-native/src/Core/Protocols/Voice/WakeWordServiceProvider.ts
- sdk/runanywhere-react-native/src/Capabilities/Memory/Services/AllocationManager.ts
- sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/index.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Models/ExecutionTarget.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Services/CostCalculator.ts
- sdk/runanywhere-react-native/src/Capabilities/Memory/Services/MemoryService.ts
- sdk/runanywhere-react-native/src/Data/Network/Services/DownloadService.ts
- sdk/runanywhere-react-native/src/Core/Models/Common/TelemetryEventType.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/StreamingService.ts
- sdk/runanywhere-react-native/src/Capabilities/ModelLoading/Services/ModelLoadingService.ts
- sdk/runanywhere-react-native/src/Capabilities/Memory/Services/PressureHandler.ts
- sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadTask.ts
- sdk/runanywhere-react-native/src/Capabilities/Memory/Services/CacheEviction.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/GenerationService.ts
- sdk/runanywhere-react-native/src/Data/Models/Downloading/DownloadState.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Services/RoutingService.ts
- sdk/runanywhere-react-native/src/Core/Models/Common/RequestPriority.ts
- sdk/runanywhere-react-native/src/Core/Protocols/Voice/WakeWordService.ts
- sdk/runanywhere-react-native/src/Core/Protocols/VLM/VLMServiceProvider.ts
- sdk/runanywhere-react-native/src/Core/Models/Configuration/WakeWordConfiguration.ts
- sdk/runanywhere-react-native/src/Core/Protocols/Component/Component.ts
- sdk/runanywhere-react-native/src/Capabilities/Memory/Services/MemoryMonitor.ts
- sdk/runanywhere-react-native/src/Core/Protocols/Lifecycle/ModelLifecycleProtocol.ts
- sdk/runanywhere-react-native/src/Core/Models/Configuration/SpeakerDiarizationConfiguration.ts
- sdk/runanywhere-react-native/src/Core/ModuleRegistry.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Models/RoutingDecision.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Models/RoutingReason.ts
- sdk/runanywhere-react-native/examples/TTSExample.tsx
- sdk/runanywhere-react-native/examples/streaming-llm-example.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/InferenceRequest.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/index.ts
- sdk/runanywhere-react-native/src/Core/Models/Configuration/VLMConfiguration.ts
- sdk/runanywhere-react-native/src/Capabilities/Routing/Services/ResourceChecker.ts
- sdk/runanywhere-react-native/src/Core/Models/Model/index.ts
- sdk/runanywhere-react-native/src/Core/Models/Configuration/LLMConfiguration.ts
- sdk/runanywhere-react-native/src/Core/Protocols/Memory/MemoryManager.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/GenerationOptionsResolver.ts
- sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Services/ThinkingParser.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-26T22:49:40.358Z
Learnt from: CR
Repo: RunanywhereAI/runanywhere-sdks PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T22:49:40.358Z
Learning: Applies to sdk/runanywhere-kotlin/**/src/**/components/**/*.kt : Implement proper component lifecycle management with initialization, state tracking, and cleanup in BaseComponent.
Applied to files:
sdk/runanywhere-react-native/src/Core/Components/BaseComponent.tssdk/runanywhere-react-native/src/Core/Models/Common/SDKComponent.ts
🧬 Code graph analysis (25)
sdk/runanywhere-react-native/src/Core/Models/Framework/FrameworkModality.ts (1)
sdk/runanywhere-react-native/src/types/index.ts (1)
FrameworkModality(12-12)
sdk/runanywhere-react-native/src/Core/Protocols/LLM/LLMService.ts (2)
sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationOptions.ts (1)
GenerationOptions(24-54)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationResult.ts (1)
GenerationResult(18-60)
sdk/runanywhere-react-native/src/Core/Protocols/Memory/MemoryModels.ts (1)
sdk/runanywhere-react-native/src/Core/Protocols/LLM/LLMService.ts (1)
LLMService(13-50)
sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Models/DeviceCapabilities.ts (2)
sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationOptions.ts (1)
HardwareAcceleration(17-17)sdk/runanywhere-react-native/src/types/index.ts (1)
HardwareAcceleration(13-13)
sdk/runanywhere-react-native/src/Core/Models/Model/ModelInfo.ts (1)
sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/ThinkingTagPattern.ts (1)
ThinkingTagPatternImpl(20-44)
sdk/runanywhere-react-native/src/Features/LLM/Errors/LLMError.ts (2)
sdk/runanywhere-react-native/src/Features/LLM/index.ts (1)
LLMError(61-61)sdk/runanywhere-react-native/src/index.ts (3)
LLMError(162-162)SDKError(66-66)ErrorCode(48-48)
sdk/runanywhere-react-native/src/Data/Protocols/Repository.ts (2)
sdk/runanywhere-react-native/src/Data/Protocols/DataSource.ts (1)
RemoteDataSource(26-57)sdk/runanywhere-react-native/src/Data/Protocols/RepositoryEntity.ts (1)
RepositoryEntity(5-17)
sdk/runanywhere-react-native/src/Core/Protocols/Voice/SpeakerDiarizationService.ts (1)
sdk/runanywhere-react-native/src/Core/Models/SpeakerDiarization/SpeakerDiarizationResult.ts (1)
SpeakerDiarizationResult(9-12)
sdk/runanywhere-react-native/src/Data/Protocols/DataSource.ts (3)
sdk/runanywhere-react-native/src/index.ts (7)
DataSource(218-218)RemoteDataSource(219-219)LocalDataSource(220-220)DataSourceStorageInfo(221-221)DataSourceError(222-222)DataSourceErrorCode(223-223)RemoteOperationHelper(224-224)sdk/runanywhere-react-native/src/Data/Protocols/index.ts (7)
DataSource(9-9)RemoteDataSource(10-10)LocalDataSource(11-11)DataSourceStorageInfo(12-12)DataSourceError(13-13)DataSourceErrorCode(14-14)RemoteOperationHelper(15-15)sdk/runanywhere-react-native/src/Infrastructure/Download/Errors/DownloadError.ts (1)
timeout(38-40)
sdk/runanywhere-react-native/src/Core/Models/Model/ModelFormat.ts (1)
sdk/runanywhere-react-native/src/index.ts (1)
ModelFormat(26-26)
sdk/runanywhere-react-native/src/Core/Capabilities/ResourceTypes.ts (2)
sdk/runanywhere-react-native/src/Core/Capabilities/index.ts (2)
CapabilityResourceType(41-41)getResourceTypeDisplayName(42-42)sdk/runanywhere-react-native/src/index.ts (1)
CapabilityResourceType(253-253)
sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts (1)
sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts (5)
CapabilityLoadingState(16-20)loadedState(39-41)loadingState(32-34)idleState(25-27)CapabilityError(265-327)
sdk/runanywhere-react-native/src/Core/Protocols/Voice/TTSService.ts (3)
sdk/runanywhere-react-native/src/index.ts (1)
TTSConfiguration(148-148)sdk/runanywhere-react-native/src/types/models.ts (2)
TTSConfiguration(339-351)TTSResult(356-368)sdk/runanywhere-react-native/src/Core/Models/Configuration/TTSConfiguration.ts (1)
TTSConfiguration(11-23)
sdk/runanywhere-react-native/src/Core/Capabilities/ManagedLifecycle.ts (7)
sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts (3)
ModelLifecycleManager(89-269)LoadResourceFn(30-33)UnloadResourceFn(39-39)sdk/runanywhere-react-native/src/Core/Capabilities/LifecycleEvents.ts (20)
createLLMModelLoadStartedEvent(35-39)createLLMModelLoadCompletedEvent(44-52)createLLMModelLoadFailedEvent(57-65)createLLMModelUnloadedEvent(70-74)createSTTModelLoadStartedEvent(92-96)createSTTModelLoadCompletedEvent(101-109)createSTTModelLoadFailedEvent(114-122)createSTTModelUnloadedEvent(127-131)createTTSModelLoadStartedEvent(149-153)createTTSModelLoadCompletedEvent(158-166)createTTSModelLoadFailedEvent(171-179)createTTSModelUnloadedEvent(184-188)createVADModelLoadStartedEvent(206-210)createVADModelLoadCompletedEvent(215-223)createVADModelLoadFailedEvent(228-236)createVADModelUnloadedEvent(241-245)createSpeakerDiarizationModelLoadStartedEvent(263-273)createSpeakerDiarizationModelLoadCompletedEvent(278-290)createSpeakerDiarizationModelLoadFailedEvent(295-307)createSpeakerDiarizationModelUnloadedEvent(312-322)sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts (2)
CapabilityLoadingState(16-20)ComponentConfiguration(124-130)sdk/runanywhere-react-native/src/Infrastructure/Events/CommonEvents.ts (3)
createErrorEvent(445-460)createModelDownloadStartedEvent(113-123)createModelDownloadCompletedEvent(152-168)sdk/runanywhere-react-native/src/Infrastructure/Events/EventPublisher.ts (1)
EventPublisher(234-237)sdk/runanywhere-react-native/src/Core/Capabilities/Analytics/CoreAnalyticsTypes.ts (1)
ModelLifecycleMetrics(59-70)sdk/runanywhere-react-native/src/Infrastructure/Events/SDKEvent.ts (1)
SDKEvent(92-133)
sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Services/HardwareCapabilityManager.ts (5)
sdk/runanywhere-react-native/src/Foundation/Logging/Logger/SDKLogger.ts (2)
SDKLogger(15-72)error(51-53)sdk/runanywhere-react-native/src/Capabilities/DeviceCapability/Models/DeviceCapabilities.ts (2)
DeviceCapabilities(54-67)DeviceCapabilitiesImpl(72-132)sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationOptions.ts (1)
HardwareAcceleration(17-17)sdk/runanywhere-react-native/src/types/models.ts (1)
ModelInfo(50-116)sdk/runanywhere-react-native/src/Core/Models/Common/ResourceAvailability.ts (1)
ResourceAvailability(24-59)
sdk/runanywhere-react-native/src/Capabilities/TextGeneration/Models/GenerationOptions.ts (2)
sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/StructuredOutputHandler.ts (1)
StructuredOutputConfig(25-30)sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/Generatable.ts (1)
StructuredOutputConfig(32-42)
sdk/runanywhere-react-native/src/Data/Network/APIEndpoint.ts (2)
sdk/runanywhere-react-native/src/Foundation/Constants/SDKConstants.ts (1)
platform(37-39)sdk/runanywhere-react-native/src/types/index.ts (1)
SDKEnvironment(22-22)
sdk/runanywhere-react-native/src/Data/Network/Services/AuthenticationService.ts (4)
sdk/runanywhere-react-native/src/Data/Network/index.ts (9)
AuthenticationService(44-44)AuthenticationProvider(41-41)APIClient(37-37)AuthenticationResponse(49-49)AuthenticationRequest(48-48)toInternalAuthResponse(55-55)HealthCheckResponse(54-54)RefreshTokenRequest(50-50)RefreshTokenResponse(51-51)sdk/runanywhere-react-native/src/Infrastructure/Device/Services/DeviceRegistrationService.ts (1)
deviceId(128-130)sdk/runanywhere-react-native/src/Foundation/Security/SecureStorageService.ts (1)
SecureStorageService(423-423)sdk/runanywhere-react-native/src/Public/Errors/SDKError.ts (2)
SDKError(15-15)SDKErrorCode(13-13)
sdk/runanywhere-react-native/src/Core/Models/Common/SDKComponent.ts (1)
sdk/runanywhere-react-native/src/types/index.ts (1)
SDKComponent(21-21)
sdk/runanywhere-react-native/src/Core/Models/Model/ModelCategory.ts (2)
sdk/runanywhere-react-native/src/index.ts (2)
ModelCategory(25-25)LLMFramework(24-24)sdk/runanywhere-react-native/src/types/index.ts (3)
ModelCategory(16-16)FrameworkModality(12-12)LLMFramework(14-14)
sdk/runanywhere-react-native/src/Data/Network/Services/NetworkService.ts (1)
sdk/runanywhere-react-native/src/index.ts (1)
APIEndpointDefinition(193-193)
sdk/runanywhere-react-native/src/Capabilities/StructuredOutput/Services/StructuredOutputHandler.ts (3)
sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/Generatable.ts (1)
StructuredOutputConfig(32-42)sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StructuredOutputGenerationService.ts (1)
StructuredOutputError(57-94)sdk/runanywhere-react-native/src/Features/LLM/StructuredOutput/StructuredOutputValidation.ts (1)
StructuredOutputError(33-69)
sdk/runanywhere-react-native/src/Features/LLM/LLMConfiguration.ts (2)
sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts (1)
ComponentConfiguration(124-130)sdk/runanywhere-react-native/src/Core/Models/Common/ComponentInitParameters.ts (1)
ComponentInitParameters(14-30)
sdk/runanywhere-react-native/src/Core/Capabilities/CapabilityProtocols.ts (3)
sdk/runanywhere-react-native/src/Core/Capabilities/index.ts (11)
CapabilityLoadingState(12-12)idleState(13-13)loadingState(14-14)loadedState(15-15)failedState(16-16)isIdle(17-17)isLoading(18-18)isLoaded(19-19)isFailed(20-20)getResourceId(21-21)Capability(28-28)sdk/runanywhere-react-native/src/index.ts (6)
CapabilityLoadingState(247-247)isIdle(248-248)isLoading(249-249)isLoaded(250-250)isFailed(251-251)Capability(241-241)sdk/runanywhere-react-native/src/Core/Capabilities/ModelLifecycleManager.ts (2)
state(137-145)isLoaded(116-118)
sdk/runanywhere-react-native/src/Data/Sync/SyncCoordinator.ts (4)
sdk/runanywhere-react-native/src/index.ts (2)
RepositoryEntity(215-215)SyncableRepository(212-212)sdk/runanywhere-react-native/src/Data/Protocols/RepositoryEntity.ts (1)
RepositoryEntity(5-17)sdk/runanywhere-react-native/src/Data/Protocols/index.ts (2)
RepositoryEntity(1-1)SyncableRepository(5-5)sdk/runanywhere-react-native/src/Data/Protocols/Repository.ts (1)
SyncableRepository(50-62)
| "@typescript-eslint/eslint-plugin": "^8.50.0", | ||
| "@typescript-eslint/parser": "^8.50.0", | ||
| "commitlint": "^17.0.2", | ||
| "del-cli": "^5.1.0", | ||
| "eslint": "^8.51.0", | ||
| "eslint-config-prettier": "^9.0.0", | ||
| "eslint-plugin-jest": "^29.5.0", | ||
| "eslint-plugin-prettier": "^5.0.1", | ||
| "eslint-plugin-unused-imports": "^4.3.0", | ||
| "glob": "^13.0.0", | ||
| "jest": "^29.7.0", | ||
| "knip": "^5.76.0", |
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.
Update ESLint minimum version to 8.57.0.
The version range of ESLint currently supported by @typescript-eslint is ^8.57.0 || ^9.0.0. The current eslint@^8.51.0 specification does not meet this requirement. Upgrade to eslint@^8.57.0 to ensure compatibility with @typescript-eslint/eslint-plugin and @typescript-eslint/parser at version 8.50.0. TypeScript 5.2.2 is within the supported range of >=4.8.4 <6.0.0, so no changes are needed for the TypeScript dependency.
🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/package.json around lines 87 to 98, eslint is
pinned to ^8.51.0 which is incompatible with @typescript-eslint@8.50.0; update
the eslint dependency to ^8.57.0 to satisfy @typescript-eslint's supported range
and ensure compatibility (leave other related linting/dependency versions
unchanged).
| results.eslint = runCommand( | ||
| 'yarn eslint "src/**/*.ts" --format json 2>&1 || true', | ||
| path.join(ITERATION_DIR, 'eslint.json') | ||
| ); | ||
|
|
||
| // 3. Knip (unused code detection) | ||
| console.log('\n[3/4] Knip (Unused Code Detection)'); | ||
| results.knip = runCommand( | ||
| 'yarn knip --reporter json 2>&1 || true', | ||
| path.join(ITERATION_DIR, 'knip.json') | ||
| ); | ||
|
|
||
| // Also get human-readable knip output | ||
| runCommand( | ||
| 'yarn knip 2>&1 || true', | ||
| path.join(ITERATION_DIR, 'knip.txt') | ||
| ); | ||
|
|
||
| // 4. TODO Check | ||
| console.log('\n[4/4] TODO Comment Check'); | ||
| results.todos = runCommand( | ||
| 'node scripts/check_todos.js 2>&1 || true', | ||
| path.join(ITERATION_DIR, 'todos.txt') | ||
| ); |
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.
|| true masks tool failures, causing incorrect success status.
Commands like yarn eslint ... || true always exit with code 0, so execSync never throws. This means results.eslint.success (and others) will always be true, even when the tools report issues. The summary will incorrectly show "PASS" for all tools.
🔎 Proposed fix
Remove || true from commands and let the catch block handle non-zero exits:
// 2. ESLint
console.log('\n[2/4] ESLint');
results.eslint = runCommand(
- 'yarn eslint "src/**/*.ts" --format json 2>&1 || true',
+ 'yarn eslint "src/**/*.ts" --format json 2>&1',
path.join(ITERATION_DIR, 'eslint.json')
);
// 3. Knip (unused code detection)
console.log('\n[3/4] Knip (Unused Code Detection)');
results.knip = runCommand(
- 'yarn knip --reporter json 2>&1 || true',
+ 'yarn knip --reporter json 2>&1',
path.join(ITERATION_DIR, 'knip.json')
);
// Also get human-readable knip output
runCommand(
- 'yarn knip 2>&1 || true',
+ 'yarn knip 2>&1',
path.join(ITERATION_DIR, 'knip.txt')
);
// 4. TODO Check
console.log('\n[4/4] TODO Comment Check');
results.todos = runCommand(
- 'node scripts/check_todos.js 2>&1 || true',
+ 'node scripts/check_todos.js 2>&1',
path.join(ITERATION_DIR, 'todos.txt')
);🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/scripts/run_analysis.js around lines 61 to 84
the shell fragments append "|| true" to eslint, knip and todo commands which
masks non-zero exits so execSync never throws and results.*.success is always
true; remove the "|| true" from those command strings (keep any necessary 2>&1
redirection) so that failing tools produce non-zero exits, allowing the existing
try/catch and result.success logic to correctly detect failures and record
output files as before.
| // Get CPU cores (sync method) | ||
| const processorCount = | ||
| DeviceInfo.getSupportedAbisSync().length > 0 | ||
| ? Math.max(2, navigator?.hardwareConcurrency ?? 4) | ||
| : 4; |
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.
navigator.hardwareConcurrency is not available in React Native.
navigator.hardwareConcurrency is a Web API that doesn't exist in React Native's JavaScript runtime. This will always be undefined, causing the fallback to 4. Additionally, checking getSupportedAbisSync().length isn't logically related to determining CPU core count.
Consider using a platform-specific approach or a reasonable default based on device model:
🔎 Proposed fix
// Get CPU cores (sync method)
- const processorCount =
- DeviceInfo.getSupportedAbisSync().length > 0
- ? Math.max(2, navigator?.hardwareConcurrency ?? 4)
- : 4;
+ // React Native doesn't expose CPU core count directly
+ // Use reasonable defaults based on platform and device era
+ const processorCount = Platform.OS === 'ios'
+ ? 6 // Modern iPhones have 6 cores (2 performance + 4 efficiency)
+ : 8; // Most modern Android devices have 8 coresAlternatively, consider removing this field or documenting it always returns an estimated value.
Committable suggestion skipped: line range outside the PR's diff.
| if (Platform.OS === 'ios') { | ||
| // A-series chips | ||
| if (device.includes('iphone16') || device.includes('ipad15')) { | ||
| return ProcessorType.A18Pro; | ||
| } | ||
| if (device.includes('iphone15') || device.includes('ipad14')) { | ||
| return ProcessorType.A17Pro; | ||
| } | ||
| if (device.includes('iphone14') || device.includes('ipad13')) { | ||
| return ProcessorType.A16Bionic; | ||
| } | ||
| if (device.includes('iphone13') || device.includes('ipad12')) { | ||
| return ProcessorType.A15Bionic; | ||
| } | ||
| if (device.includes('iphone12') || device.includes('ipad11')) { | ||
| return ProcessorType.A14Bionic; | ||
| } | ||
|
|
||
| // M-series (iPad Pro, Mac) | ||
| if (device.includes('mac') || device.includes('ipad14')) { | ||
| return ProcessorType.M2; | ||
| } | ||
| } |
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.
Incorrect Apple device identifier to processor mapping.
Apple's device identifiers don't match marketing names. For example:
iPhone16,x= iPhone 15 series (A16/A17 Pro)iPhone15,x= iPhone 14 series (A15/A16)iPhone14,x= iPhone 13 series (A15)
The current logic will misidentify processors. Also, line 382 checks ipad14 for M2 after line 368 already matched it for A17Pro.
🔎 Proposed fix with correct mappings
private detectProcessorType(
deviceId: string,
supportedAbis: string[]
): ProcessorType {
const device = deviceId.toLowerCase();
if (Platform.OS === 'ios') {
- // A-series chips
- if (device.includes('iphone16') || device.includes('ipad15')) {
- return ProcessorType.A18Pro;
- }
- if (device.includes('iphone15') || device.includes('ipad14')) {
- return ProcessorType.A17Pro;
- }
- if (device.includes('iphone14') || device.includes('ipad13')) {
- return ProcessorType.A16Bionic;
- }
- if (device.includes('iphone13') || device.includes('ipad12')) {
- return ProcessorType.A15Bionic;
- }
- if (device.includes('iphone12') || device.includes('ipad11')) {
- return ProcessorType.A14Bionic;
- }
-
- // M-series (iPad Pro, Mac)
- if (device.includes('mac') || device.includes('ipad14')) {
- return ProcessorType.M2;
- }
+ // Extract numeric identifier (e.g., "iphone17,1" -> 17)
+ const iPhoneMatch = device.match(/iphone(\d+)/);
+ if (iPhoneMatch) {
+ const generation = parseInt(iPhoneMatch[1], 10);
+ // iPhone17,x = iPhone 16 (A18/A18 Pro)
+ if (generation >= 17) return ProcessorType.A18Pro;
+ // iPhone16,x = iPhone 15 (A16/A17 Pro)
+ if (generation === 16) return ProcessorType.A17Pro;
+ // iPhone15,x = iPhone 14 (A15/A16)
+ if (generation === 15) return ProcessorType.A16Bionic;
+ // iPhone14,x = iPhone 13 (A15)
+ if (generation === 14) return ProcessorType.A15Bionic;
+ // iPhone13,x = iPhone 12 (A14)
+ if (generation === 13) return ProcessorType.A14Bionic;
+ }
+
+ // M-series detection for iPad/Mac
+ if (device.includes('mac')) {
+ return ProcessorType.M2;
+ }
}Committable suggestion skipped: line range outside the PR's diff.
| // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ModelDiscovery type not yet defined | ||
| private modelDiscovery: any; | ||
| private readonly logger = new SDKLogger('RegistryService'); |
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:
#!/bin/bash
# Find and examine the RegistryService.ts file
fd -t f 'RegistryService.ts' --exec cat -n {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 6337
🏁 Script executed:
#!/bin/bash
# Check the ServiceContainer implementation
fd -t f 'ServiceContainer.ts' --exec cat -n {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 12009
modelDiscovery field is never initialized and typed as any.
The field is declared but never assigned in the constructor or through any initialization mechanism, so this.modelDiscovery?.discoverLocalModels() on line 38 will always return undefined (falling back to []). Model discovery functionality cannot work unless this field is properly initialized via dependency injection or a setter method.
Additionally, the _apiKey parameter in the initialize method is unused, and registerModelPersistently has its persistence logic commented out, making it non-functional.
| /** Timestamp of when the result was created */ | ||
| timestamp: Date; |
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.
Date type doesn't survive React Native bridge serialization.
The timestamp field is typed as Date, but data crossing the RN bridge (via JSON serialization) will arrive as a string (ISO format) or number, not a Date instance. Calling result.timestamp.getTime() or similar methods will fail at runtime.
Consider using number (epoch milliseconds) or string (ISO format) to match the actual serialized representation, or add a note that consumers must manually convert.
🔎 Suggested fix using number (epoch milliseconds)
- /** Timestamp of when the result was created */
- timestamp: Date;
+ /** Timestamp of when the result was created (epoch milliseconds) */
+ timestamp: number;📝 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.
| /** Timestamp of when the result was created */ | |
| timestamp: Date; | |
| /** Timestamp of when the result was created (epoch milliseconds) */ | |
| timestamp: number; |
🤖 Prompt for AI Agents
sdk/runanywhere-react-native/src/Core/Models/TTS/TTSResult.ts around lines 53 to
54, the timestamp is typed as Date which is not preserved across the React
Native bridge (JSON serialization yields a string or number), so update the type
to a serialized form (prefer number representing epoch milliseconds) and adjust
the JSDoc to state that timestamp is epoch ms; ensure any code constructing
TTSResult sets timestamp to Date.now() (or converts Date to .getTime()) and any
consumers convert the number back to a Date if needed.
| const SDK_CONSTANTS = { | ||
| clientName: 'RunAnywhereSDK-RN', | ||
| version: '0.1.0', | ||
| platform: 'react-native', | ||
| } as const; |
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:
#!/bin/bash
# Check for version string 0.1.0 and SDKConstants usage across the codebase
echo "=== Searching for version 0.1.0 ==="
rg "0\.1\.0" --type=ts --type=js -n
echo ""
echo "=== Searching for SDKConstants references ==="
rg "SDKConstants" --type=ts --type=js -n -B2 -A2
echo ""
echo "=== Checking if constants are imported elsewhere ==="
rg "version" --type=ts --type=json | grep -i "constant\|const" | head -20Repository: RunanywhereAI/runanywhere-sdks
Length of output: 5689
Import version from centralized SDKConstants instead of defining a local constant.
APIClient.ts defines its own local SDK_CONSTANTS with version '0.1.0' on line 23, but a centralized SDKConstants module already exists at sdk/runanywhere-react-native/src/Foundation/Constants/SDKConstants.ts with version '0.15.8'. This creates version inconsistency across the codebase. Import SDKConstants from '../Foundation/Constants/SDKConstants' and use SDKConstants.version instead of maintaining a local duplicate.
🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/src/Data/Network/Services/APIClient.ts around
lines 21 to 25, the file defines a local SDK_CONSTANTS object with a hardcoded
version ('0.1.0'); replace this local constant by importing the centralized
SDKConstants from ../Foundation/Constants/SDKConstants and use
SDKConstants.version (and optionally SDKConstants.clientName/platform if
available) so the module relies on the single source of truth for the SDK
version and avoids duplication.
| post<T, R>( | ||
| endpoint: APIEndpoint | APIEndpointDefinition, | ||
| payload: T, | ||
| requiresAuth?: boolean | ||
| ): Promise<R>; | ||
|
|
||
| /** | ||
| * Perform a GET request | ||
| * Perform a typed GET request | ||
| */ | ||
| get<R>(endpoint: APIEndpoint, requiresAuth?: boolean): Promise<R>; | ||
| get<R>( | ||
| endpoint: APIEndpoint | APIEndpointDefinition, | ||
| requiresAuth?: boolean | ||
| ): Promise<R>; | ||
|
|
||
| /** | ||
| * Perform a raw POST request (returns Data) | ||
| * Perform a raw POST request (returns ArrayBuffer/Data) | ||
| */ | ||
| postRaw(endpoint: APIEndpoint, payload: ArrayBuffer, requiresAuth?: boolean): Promise<ArrayBuffer>; | ||
| postRaw( | ||
| endpoint: APIEndpoint | APIEndpointDefinition, | ||
| payload: ArrayBuffer, | ||
| requiresAuth?: boolean | ||
| ): Promise<ArrayBuffer>; | ||
|
|
||
| /** | ||
| * Perform a raw GET request (returns Data) | ||
| * Perform a raw GET request (returns ArrayBuffer/Data) | ||
| */ | ||
| getRaw(endpoint: APIEndpoint, requiresAuth?: boolean): Promise<ArrayBuffer>; | ||
| getRaw( | ||
| endpoint: APIEndpoint | APIEndpointDefinition, | ||
| requiresAuth?: boolean | ||
| ): Promise<ArrayBuffer>; |
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:
#!/bin/bash
# Find and examine the NetworkService file
fd -t f NetworkService.ts --exec cat {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 3854
🏁 Script executed:
#!/bin/bash
# Find APIEndpointDefinition definition
fd -t f APIEndpoint.ts --exec cat {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 5335
🏁 Script executed:
#!/bin/bash
# Verify the type compatibility by checking if the interfaces are truly identical
cat <<'EOF' > /tmp/type_check.ts
import type { APIEndpoint } from './NetworkService';
import type { APIEndpointDefinition } from './APIEndpoint';
// Check structural compatibility
const apiEndpoint: APIEndpoint = { path: '/test', method: 'GET' };
const apiEndpointDef: APIEndpointDefinition = { path: '/test', method: 'GET' };
// Can we assign one to the other?
const test1: APIEndpoint = apiEndpointDef; // Does this work?
const test2: APIEndpointDefinition = apiEndpoint; // Does this work?
EOF
# Search for any actual usage of NetworkServiceImpl methods to see if union type is ever used
rg "new NetworkServiceImpl|NetworkServiceImpl" --type=ts -A5 -B5Repository: RunanywhereAI/runanywhere-sdks
Length of output: 1906
🏁 Script executed:
#!/bin/bash
# Check if TypeScript compilation would catch this error
# Look for tsconfig and check strict mode settings
fd -t f tsconfig.json --exec cat {} \;Repository: RunanywhereAI/runanywhere-sdks
Length of output: 1887
Update NetworkServiceImpl to match interface parameter types
The NetworkService interface declares methods accepting APIEndpoint | APIEndpointDefinition, but NetworkServiceImpl implementations (lines 73, 93, 103, 133) only accept APIEndpoint. This violates the Liskov Substitution Principle and creates a type contract mismatch. While APIEndpoint and APIEndpointDefinition are structurally identical, the interface declares a broader contract that the implementation must honor.
Update all four methods in NetworkServiceImpl to accept the union type:
post<T, R>(endpoint: APIEndpoint | APIEndpointDefinition, ...)get<R>(endpoint: APIEndpoint | APIEndpointDefinition, ...)postRaw(endpoint: APIEndpoint | APIEndpointDefinition, ...)getRaw(endpoint: APIEndpoint | APIEndpointDefinition, ...)
🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/src/Data/Network/Services/NetworkService.ts
around lines 31-60 (and update implementations at ~73, 93, 103, 133), the
interface methods accept APIEndpoint | APIEndpointDefinition but
NetworkServiceImpl methods currently only accept APIEndpoint; change the four
implementation method signatures (post, get, postRaw, getRaw) to accept the
union type APIEndpoint | APIEndpointDefinition so the class conforms to the
interface contract; ensure any internal usage still treats the endpoint as the
same structural type (no runtime changes required) and update any related type
annotations or imports if necessary.
| // eslint-disable-next-line @typescript-eslint/no-explicit-any -- SyncCoordinator type not yet defined | ||
| private syncCoordinator: any | null; |
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 any type with proper SyncCoordinator type.
The use of any for syncCoordinator removes type safety and could lead to runtime errors. While the comment indicates the type is "not yet defined," the AI summary mentions SyncCoordinator.ts exists with a sync<T> method.
🔎 Suggested approach
Import the SyncCoordinator type and update the typing:
+import type { SyncCoordinator } from '../Sync/SyncCoordinator';
+
export class ModelInfoService {
private logger: SDKLogger;
private modelInfoRepository: ModelInfoRepository;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- SyncCoordinator type not yet defined
- private syncCoordinator: any | null;
+ private syncCoordinator: SyncCoordinator | null;And in the constructor:
constructor(
modelInfoRepository: ModelInfoRepository,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- SyncCoordinator type not yet defined
- syncCoordinator?: any | null
+ syncCoordinator?: SyncCoordinator | null
) {Also applies to: 33-34
🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/src/Data/Services/ModelInfoService.ts around
lines 21-22 and 33-34, the syncCoordinator field and related constructor/use
sites are typed as any; replace those any types with the actual SyncCoordinator
interface to restore type safety: import the SyncCoordinator type from its
module (where SyncCoordinator.ts lives), change the private syncCoordinator
declaration to SyncCoordinator | null, update the constructor parameter and any
assignments to use SyncCoordinator (or nullable) and adjust calls to sync<T> to
match the generic signature; ensure imports and nullable checks (if any) compile
without changing runtime behavior.
| static noProviderFound(modelId?: string): LLMError { | ||
| const message = modelId | ||
| ? `No LLM provider found for model: ${modelId}` | ||
| : 'No LLM provider registered. Register one with ModuleRegistry.shared.registerLLM(provider).'; | ||
| return new LLMError(ErrorCode.ModelNotFound, message, { | ||
| details: { modelId }, | ||
| }); | ||
| } |
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:
# Search for ModuleRegistry class definition and usage in the codebase
rg -nP 'class ModuleRegistry|ModuleRegistry\s*\{' -A5 -B2
# Search for ServiceRegistry definition and LLM registration
rg -nP 'ServiceRegistry|registerLLM' -A3 -B3
# Check if ModuleRegistry exists in the codebase at all
fd -t f '\.ts$|\.tsx$|\.js$' | xargs grep -l 'ModuleRegistry' | head -20Repository: RunanywhereAI/runanywhere-sdks
Length of output: 50388
🏁 Script executed:
# Get the exact method signature from ServiceRegistry
sed -n '590,610p' sdk/runanywhere-react-native/src/Foundation/DependencyInjection/ServiceRegistry.tsRepository: RunanywhereAI/runanywhere-sdks
Length of output: 754
Update the LLM provider registration API reference in the error message.
Line 33 references ModuleRegistry.shared.registerLLM(provider), but this API does not exist in the React Native SDK. The correct method is ServiceRegistry.shared.registerLLMProvider(provider). Update the error message to guide users to the actual registration API.
🤖 Prompt for AI Agents
In sdk/runanywhere-react-native/src/Features/LLM/Errors/LLMError.ts around lines
30 to 37, the error message references a non-existent API
ModuleRegistry.shared.registerLLM(provider); update the message to point to the
correct React Native SDK method
ServiceRegistry.shared.registerLLMProvider(provider). Edit the message string
used when modelId is undefined so users are guided to call
ServiceRegistry.shared.registerLLMProvider(provider) instead of the old
ModuleRegistry API.
- Updated type parameters in StructuredOutputHandler and DataSource interfaces for improved clarity and consistency. - Enhanced error handling in SyncCoordinator to ensure remote data source availability before syncing batches. - Specified type for preferredFramework in LLMGenerationOptions to improve type safety and maintainability.
- Updated SettingsScreen to convert string capabilities to numeric indices for better display mapping. - Enhanced STT and TTS screens to utilize model categories instead of types for improved clarity. - Improved error handling in SecureStorageService and DeviceIdentityService by logging errors with structured objects. - Streamlined type exports and added new type declarations for better type safety across various modules. - Introduced type declarations for react-native-fs to enhance file handling capabilities. - Refactored APIClient to handle null access tokens gracefully, ensuring fallback to API key when necessary.
- Updated App.tsx to implement two-phase SDK initialization and module registration for LlamaCPP and ONNX models. - Added detailed model registration logic for LlamaCPP and ONNX, including multiple model definitions with memory requirements and download URLs. - Enhanced ChatScreen, STTScreen, TTSScreen, SettingsScreen, and VoiceAssistantScreen with comprehensive architecture descriptions and feature lists, aligning with iOS counterparts. - Introduced new Modules index file to streamline module exports and improve organization. - Added LlamaCPP and ONNX module wrappers to provide a consistent API for model registration and management.
- Updated App.tsx to improve SDK initialization with useCallback for better performance. - Introduced knip.json for managing unused imports and enhancing code quality. - Refactored multiple components to improve code readability and maintainability by restructuring imports and applying consistent formatting. - Enhanced package.json and package-lock.json with updated dependencies for better development experience. - Streamlined type imports across various files to ensure clarity and consistency in type usage. - Removed obsolete NativeAudioModule to simplify the audio handling structure.
…atures - Updated SettingsScreen to integrate new SDK API for retrieving storage information and managing downloaded models. - Refactored VoiceAssistantScreen to implement a complete voice processing pipeline, including audio recording, transcription, LLM response generation, and TTS synthesis. - Introduced new extensions for Voice Session, Voice Agent, and Storage Management, providing modular capabilities for voice interactions and storage handling. - Improved error handling and logging throughout the voice processing and storage management functionalities. - Streamlined imports and exports across the SDK to enhance organization and maintainability.
Resolved Package.resolved conflict by accepting dev branch version.
…new native bridges for enhanced functionality - Deleted multiple unused capability and service files across core functionalities, including DeviceCapability, TextGeneration, and Analytics. - Added new native bridges for Android and iOS to improve integration with the RunAnywhere framework. - Updated package configurations and build scripts to support the new architecture.
…ga/react_native_rearch
…abilities - Added VoiceSession feature module to manage audio capture and playback for voice assistant integration. - Implemented AudioCaptureManager and AudioPlaybackManager for handling audio recording and playback. - Created VoiceSessionHandle for high-level voice session management. - Re-exported new features in the core SDK index for easier access. - Updated type definitions for voice session events and configurations. - Removed outdated device registration service and common events definitions from the infrastructure module.
… files
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
Greptile Summary
This PR implements a major architectural refactoring to align the React Native SDK with the iOS SDK structure. The changes introduce a clean separation of concerns following iOS patterns:
Major Changes:
Core/,Features/,Foundation/, andInfrastructure/matching iOS architectureManagedLifecycleclass handles model loading/unloading with integrated event trackingServiceRegistryreplaces separateModuleRegistryand factory registriesFoundation/ErrorTypes/with numeric error codes, categories, and context tracking (supports legacy string codes for backward compatibility)VoiceSessionHandlefor React Native audio capture integrationLLMCapability,STTCapability,TTSCapability,VADCapability, andSpeakerDiarizationCapabilitywith consistent patternsRemoved:
streaming-llm-example.ts,TTSExample.tsx)Key Improvements:
EventPublisherrouting to both publicEventBusand analyticsIssues Found:
setTimeoutwhich makes error handling non-deterministic - failures are logged but never surface to callerSDKConstants.versionConfidence Score: 3/5
src/Public/RunAnywhere.ts(initialization error handling),src/Infrastructure/Device/Services/DeviceRegistrationService.ts(version strings), andsrc/Infrastructure/ModelManagement/Services/ModelAssignmentService.ts(device type detection)Important Files Changed
Sequence Diagram
sequenceDiagram participant App as Application participant SDK as RunAnywhere SDK participant Core as Core/Foundation participant Services as ServiceRegistry participant Lifecycle as ManagedLifecycle participant Feature as LLM/STT/TTS Capability participant Provider as Framework Provider participant Native as Native Module Note over App,Native: Two-Phase Initialization App->>SDK: initialize(options) activate SDK Note over SDK,Core: Phase 1: Core (Sync, ~1-5ms) SDK->>Core: Validate config SDK->>Native: createBackend('llamacpp') Native-->>SDK: Backend created SDK->>Native: initialize(config) Native-->>SDK: Initialized SDK->>SDK: markCoreInitialized() SDK-->>App: isSDKInitialized = true Note over SDK,Services: Phase 2: Services (Async, ~100-500ms) SDK->>SDK: _startPhase2InBackground() deactivate SDK par Background Initialization SDK->>Services: registerProviders() Services->>Provider: LlamaCppProvider.register() Services->>Provider: ONNXProvider.register() SDK->>Services: ModelRegistry.initialize() SDK->>SDK: markServicesInitialized() end Note over App,Native: Model Loading & Generation App->>SDK: loadModel(modelId) SDK->>Feature: LLMCapability.loadModel() activate Feature Feature->>Lifecycle: load(modelId) activate Lifecycle Lifecycle->>Lifecycle: Emit loadStarted event Lifecycle->>Services: llmProvider(modelId) Services-->>Lifecycle: Provider instance Lifecycle->>Provider: createLLMService(config) Provider->>Native: Create native service Native-->>Provider: Service handle Provider-->>Lifecycle: LLMService Lifecycle->>Lifecycle: Emit loadCompleted event Lifecycle-->>Feature: Service loaded deactivate Lifecycle Feature-->>SDK: Model loaded deactivate Feature App->>SDK: generate(prompt, options) SDK->>Feature: LLMCapability.generate() activate Feature Feature->>Provider: service.generate() Provider->>Native: native.generate() Native-->>Provider: Result Provider-->>Feature: GenerationResult Feature->>Feature: Track analytics metrics Feature->>Lifecycle: Emit generation event Feature-->>SDK: Result with metrics deactivate Feature SDK-->>App: GenerationResult Note over App,Native: Cleanup App->>SDK: unloadModel() SDK->>Feature: unloadModel() Feature->>Lifecycle: unload() activate Lifecycle Lifecycle->>Lifecycle: Emit unloaded event Lifecycle->>Provider: service.cleanup() Provider->>Native: Release resources Lifecycle-->>Feature: Unloaded deactivate Lifecycle Feature-->>SDK: Success SDK-->>App: SuccessSummary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.