Conversation
- Updated HistoryTable to implement infinite scrolling for loading history items dynamically. - Introduced state management for accumulated history and total item count. - Added Intersection Observer for triggering additional data fetches when scrolling. - Implemented cache clearing functionality in the backend to manage voice prompt caches effectively. - Improved loading indicators and user feedback for data fetching states. - Refactored code for better readability and maintainability.
- Rearranged import statements for consistency and clarity. - Corrected the spelling of "interchangeable" in the note about sample quality.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| cache_file.unlink() | ||
| deleted_count += 1 | ||
| except Exception as e: | ||
| print(f"Failed to delete cache file {cache_file}: {e}") |
There was a problem hiding this comment.
Cache clearing omits combined audio WAV files
Medium Severity
The new clear_voice_prompt_cache() function only deletes *.prompt files, but this PR introduces combined audio files stored as combined_{profile_id}_{hash}.wav in the same cache directory. These .wav files are never cleaned up - not when clearing the cache, not when samples are deleted, and not when profiles change. Over time, this causes orphaned files to accumulate.
Additional Locations (1)
| setPage(0); | ||
| setAllHistory([]); | ||
| } | ||
| }, [deleteGeneration.isSuccess, importGeneration.isSuccess]); |
There was a problem hiding this comment.
Deleted items briefly reappear due to race condition
Low Severity
When a deletion or import succeeds, the reset effect sets page to 0 and clears allHistory. However, because page changed, the historyData effect immediately runs with the stale historyData (refetch hasn't completed), setting allHistory back to the old items—including any just-deleted item. This causes deleted items to briefly reappear until the refetch completes.
Additional Locations (1)
| reference_texts, | ||
| ) | ||
|
|
||
| # Save combined audio temporarily |
There was a problem hiding this comment.
Profile deletion leaves orphaned combined audio cache files
Low Severity
The new combined audio files are stored in the cache directory as combined_{profile_id}_{hash}.wav, but delete_profile() only deletes the profile directory. When a profile is deleted, its combined audio cache files remain orphaned in the cache directory indefinitely. The profile_id is embedded in the filename, so cleanup is straightforward but currently absent.
- Added `clear_profile_cache` function to manage cache files for specific profiles. - Integrated cache clearing in `add_profile_sample`, `delete_profile`, and `delete_profile_sample` functions to ensure stale audio caches are invalidated after modifications. - Enhanced `clear_voice_prompt_cache` to also delete combined audio files, improving overall cache management.
…ents - Implemented delete confirmation dialogs for both HistoryTable and SampleList components to enhance user experience and prevent accidental deletions. - Added state management for handling the selected item to be deleted and the visibility of the delete dialog. - Refactored delete handling functions to utilize the new dialog confirmation flow, improving code clarity and maintainability.
- Added a default `type` prop set to 'button' in the CircleButton component to ensure proper button behavior. - Enhanced the component's flexibility by allowing the type to be overridden through props.


Fix voice cloning with multiple samples fallback to default voice
Closes #18
Summary
Fixed a critical bug where voice profiles with multiple samples would fall back to the default Qwen voice instead of using the cloned voice. The issue was caused by temporary files being deleted before generation could use them.
Changes
Backend:
backend/profiles.py: Changed combined audio storage from temporary files to persistent cache files (data/cache/combined_{profile_id}_{hash}.wav)backend/backends/mlx_backend.py: Added validation to check cached audio files exist before use, with automatic regeneration if missingbackend/backends/pytorch_backend.py: Updated cache validation logic for consistencybackend/utils/cache.py: Addedclear_voice_prompt_cache()function to clear stale cache entriesbackend/main.py: AddedPOST /cache/clearendpoint for manual cache clearingFrontend:
app/src/components/VoiceProfiles/SampleList.tsx: Added informational note that single 30-second samples produce optimal qualityTechnical Details
When multiple samples were combined, the system created a temp file, generated a voice prompt (storing the file path), then immediately deleted the temp file. This caused the MLX backend to fail during generation since it stores file paths rather than loading audio into memory. The fix ensures combined audio persists in the cache directory.
Note
Medium Risk
Touches core voice-cloning prompt creation/caching and adds a new cache-clearing API, so regressions could affect generation quality or cache behavior, though changes are localized and guarded with validation/fallbacks.
Overview
Fixes voice cloning for profiles with multiple samples by persisting the combined reference audio in the cache directory (instead of a temp file that could be deleted before generation) and hardening cached-prompt usage.
The MLX backend now verifies cached
ref_audiopaths exist (both when creating and when generating) and falls back to non-cloned generation if the referenced audio is missing; PyTorch cache handling is clarified for dict-vs-tensor prompt formats. Addsclear_voice_prompt_cache()plus a newPOST /cache/clearendpoint to purge stale prompt entries.On the frontend,
HistoryTablegains infinite scrolling with accumulated paging, loading indicators, and end-of-list messaging, andSampleListadds a short guidance note about optimal sample usage.Written by Cursor Bugbot for commit 953e6ec. Configure here.