Skip to content

Whisper download fix#312

Merged
dishit-wednesday merged 5 commits into
mainfrom
whisper-download-fix
Apr 21, 2026
Merged

Whisper download fix#312
dishit-wednesday merged 5 commits into
mainfrom
whisper-download-fix

Conversation

@dishit-wednesday

Copy link
Copy Markdown
Collaborator

Summary

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (code change that neither fixes a bug nor adds a feature)
  • Chore (build process, CI, dependency updates, etc.)

Screenshots / Screen Recordings

Android

Before After

iOS

Before After

Checklist

General

  • My code follows the project's coding style and conventions
  • I have performed a self-review of my code
  • I have added/updated comments where the logic isn't self-evident
  • My changes generate no new warnings or errors

Testing

  • I have tested on Android (physical device or emulator)
  • I have tested on iOS (physical device or simulator)
  • I have tested in light mode and dark mode
  • Existing tests pass locally (npm test)
  • I have added tests that prove my fix is effective or my feature works

React Native Specific

  • No new native module without corresponding platform implementation (Android + iOS)
  • New native modules are added to the Xcode project build target (project.pbxproj)
  • No hardcoded pixel values — uses SPACING / TYPOGRAPHY constants from the theme
  • Styles use useThemedStyles pattern (not inline or static StyleSheet.create)
  • Animations/gestures work smoothly on both platforms
  • Large lists use FlatList / FlashList (not .map() inside ScrollView)
  • No unnecessary re-renders introduced (check with React DevTools Profiler if unsure)

Performance & Models

  • Downloads / long-running tasks report progress to the UI
  • File paths are resolved correctly on both platforms (no hardcoded / vs \\)
  • Large files (models, assets) are not committed to the repository

Security

  • No secrets, API keys, or credentials are included in the code
  • User input is validated/sanitized where applicable

Related Issues

Additional Notes

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a "Paste Text" feature for the knowledge base, including a new AddTextModal component and a corresponding indexTextContent method in the RAG service. It also refactors whisperService to utilize the backgroundDownloadService for model downloads and removes the native Android DownloadForegroundService, shifting progress tracking to the JavaScript layer. Review feedback identifies a potential race condition in tracking active download IDs, a path traversal vulnerability when generating filenames from user-provided titles, and opportunities to improve input validation and error-state file cleanup.

Comment thread src/services/whisperService.ts Outdated
Comment on lines +66 to +68
downloadIdPromise.then(id => { this.activeDownloadId = id; }).catch(() => {});
try {
await promise;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

There is a potential race condition here. activeDownloadId is set asynchronously via .then(). If deleteModel is called immediately after downloadModel starts but before the promise resolves, activeDownloadId will still be null, and the background download will not be cancelled. Awaiting the ID before awaiting the download completion reduces this window.

Suggested change
downloadIdPromise.then(id => { this.activeDownloadId = id; }).catch(() => {});
try {
await promise;
try {
this.activeDownloadId = await downloadIdPromise;
await promise;

Comment thread src/components/AddTextModal.tsx Outdated
Comment on lines +110 to +113
const charCount = text.length;
const tooShort = charCount > 0 && charCount < MIN_CHARS;
const tooLong = charCount > PASTE_MAX_CHARS;
const canSave = charCount >= MIN_CHARS && !tooLong && !indexing;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The character count and validation should ideally use the trimmed text length. Currently, a user could bypass the MIN_CHARS requirement by entering only whitespace, which would later fail during the indexing process when no chunks are produced.

Suggested change
const charCount = text.length;
const tooShort = charCount > 0 && charCount < MIN_CHARS;
const tooLong = charCount > PASTE_MAX_CHARS;
const canSave = charCount >= MIN_CHARS && !tooLong && !indexing;
const charCount = text.trim().length;
const tooShort = charCount > 0 && charCount < MIN_CHARS;
const tooLong = text.length > PASTE_MAX_CHARS;
const canSave = charCount >= MIN_CHARS && !tooLong && !indexing;

Comment thread src/services/rag/index.ts Outdated
const { projectId, title, text, onProgress } = params;
await this.ensureReady();

const baseName = title.trim() || 'Note';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The baseName is derived directly from the user-provided title without sanitization. This could lead to path traversal issues. As per project rules, sanitize the filename by extracting only the last component of the path (e.g., using .split('/').pop()) to ensure the file remains within the intended directory.

Suggested change
const baseName = title.trim() || 'Note';
const baseName = title.split('/').pop() || 'Note';
References
  1. When extracting filenames from user input (e.g., from a document picker URI), always sanitize the filename to prevent path traversal vulnerabilities. This can be achieved by extracting only the last component of the path (e.g., using .split('/').pop()) to ensure the file remains within the intended directory.

Comment on lines 78 to 80
} catch (validationError) {
await RNFS.unlink(destPath).catch(() => {});
throw new Error(`Downloaded model file is invalid: ${validationError instanceof Error ? validationError.message : 'unknown error'}`);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If the model file fails validation after a successful download, it should be deleted to prevent leaving a corrupt or invalid file in the models directory. Ensure that any errors during deletion are logged rather than swallowed, adhering to the project's error handling rules.

Suggested change
} catch (validationError) {
await RNFS.unlink(destPath).catch(() => {});
throw new Error(`Downloaded model file is invalid: ${validationError instanceof Error ? validationError.message : 'unknown error'}`);
}
} catch (validationError) {
await RNFS.unlink(destPath).catch(err => console.error('Failed to delete invalid model:', err));
throw new Error("Downloaded model file is invalid: " + (validationError instanceof Error ? validationError.message : "unknown error"));
}
References
  1. When catching errors, log them instead of swallowing them to ensure failures are visible and to aid in debugging.

dishit-wednesday and others added 3 commits April 21, 2026 13:49
…nloadService

Co-authored-by: Dishit <hanmadishit74@gmail.com>
…d service crashes

Co-authored-by: Dishit <hanmadishit74@gmail.com>
…ve to 7.1.0

Removes DownloadForegroundServiceTest.kt which referenced the now-deleted
DownloadForegroundService class, fixing Android compilation. Upgrades
react-native-zip-archive from 7.0.2 to 7.1.0 to fix the NPE crash when
rejecting a promise with a null code (issue #336). Runs pod install to sync
iOS Podfile.lock after the package upgrade.

Co-Authored-By:Dishit <hanmadishit74@gmail.com>
dishit-wednesday and others added 2 commits April 21, 2026 13:55
Co-authored-by: Dishit <hanmadishit74@gmail.com>
…ompile error

Java does not allow switch on double. Cast compressionLevel to int so the
switch compiles. Patch auto-applies via patch-package postinstall on CI.

Co-authored-by: Dishit <hanmadishit74@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Apr 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.75000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.84%. Comparing base (1caade1) to head (f401199).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
src/services/whisperService.ts 68.75% 3 Missing and 2 partials ⚠️

❌ Your patch status has failed because the patch coverage (68.75%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #312      +/-   ##
==========================================
- Coverage   83.85%   83.84%   -0.02%     
==========================================
  Files         224      224              
  Lines       11478    11487       +9     
  Branches     3145     3147       +2     
==========================================
+ Hits         9625     9631       +6     
- Misses       1070     1072       +2     
- Partials      783      784       +1     
Files with missing lines Coverage Δ
src/services/whisperService.ts 79.88% <68.75%> (-1.37%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dishit-wednesday dishit-wednesday merged commit cafc19d into main Apr 21, 2026
6 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant