Skip to content

fix(export): disambiguate export filenames with generation id - #956

Merged
jamiepine merged 1 commit into
jamiepine:mainfrom
ivancorsetti:fix/export-filename-collision
Jul 27, 2026
Merged

fix(export): disambiguate export filenames with generation id#956
jamiepine merged 1 commit into
jamiepine:mainfrom
ivancorsetti:fix/export-filename-collision

Conversation

@ivancorsetti

@ivancorsetti ivancorsetti commented Jul 23, 2026

Copy link
Copy Markdown

Problem

Export filenames are derived from only the first 30 characters of the generation text:

  • backend/routes/history.pyContent-Disposition for /history/{id}/export-audio ({text}.wav) and /history/{id}/export (generation-{text}.voicebox.zip)
  • app/src/lib/hooks/useHistory.ts — the filename passed to platform.filesystem.saveFile in both export hooks

When iterating on the same line — a very common workflow — generations share the same 30-char prefix and therefore get identical filenames. Exporting several of them collides on disk: the browser appends (1)/ (2), and users end up opening audio that doesn't match the filename, which looks like the app exported the wrong audio.

Reproduction

Two distinct generations whose text both starts with "Martina se fai la brava stasera puoi rientrare domani…":

Generation Size md5 Filename (before)
95ac48a0… 311 KB 63967a68… Martina se fai la brava staser.wav
4ed9b3cc… 200 KB 0c404d44… Martina se fai la brava staser.wav

Different audio, identical filename.

Fix

Append the first 8 characters of the generation id to the .wav and .voicebox.zip export filenames, in both the backend Content-Disposition headers and the frontend save-file hooks.

After the fix:

95ac48a0 -> Martina se fai la brava staser-95ac48a0.wav
4ed9b3cc -> Martina se fai la brava staser-4ed9b3cc.wav

Testing

  • Verified both /export-audio and /export now return unique Content-Disposition filenames for the colliding pair above, against a running backend.
  • tsc -p app/tsconfig.json --noEmit — passes.
  • biome lint on the changed file — clean.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Exported Voicebox ZIP and WAV files now include a unique identifier in their filenames.
    • Prevented files from being unintentionally overwritten when exports have similar text or names.

Export filenames were derived from only the first 30 characters of the
generation text. Generations with similar wording (a common workflow when
iterating on the same line) produced identical filenames, so exports
collided on disk — the browser appended " (1)"/" (2)" and users ended up
opening audio that didn't match the expected filename.

Append the first 8 chars of the generation id to the .wav and .voicebox.zip
export filenames, in both the backend Content-Disposition headers and the
frontend save-file hooks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Export filenames for voicebox ZIP and audio WAV downloads now combine sanitized text prefixes with the first eight characters of each generation identifier in both frontend and backend history flows.

Changes

Export filename generation

Layer / File(s) Summary
Add generation identifiers to export filenames
backend/routes/history.py, app/src/lib/hooks/useHistory.ts
ZIP and WAV filenames now append generation_id[:8] or its frontend equivalent to the sanitized, truncated text prefix.

Estimated code review effort: 1 (Trivial) | ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding generation-id suffixes to export filenames to avoid collisions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
app/src/lib/hooks/useHistory.ts (1)

50-57: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Keep frontend and backend filename sanitization consistent.

The frontend replaces invalid characters with - and lowercases the text, while backend/routes/history.py removes invalid characters and preserves case. The same export can therefore receive different filenames depending on the download path. Reuse a shared convention or explicitly document that these names intentionally differ.

Also applies to: 78-85

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/lib/hooks/useHistory.ts` around lines 50 - 57, Align the filename
sanitization in the frontend export logic around safeText and filename with the
backend history route’s convention, so both download paths produce identical
names. Reuse a shared sanitization rule where available; otherwise update the
frontend transformations to match the backend behavior and apply the same change
to the additional filename construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/src/lib/hooks/useHistory.ts`:
- Around line 50-57: Align the filename sanitization in the frontend export
logic around safeText and filename with the backend history route’s convention,
so both download paths produce identical names. Reuse a shared sanitization rule
where available; otherwise update the frontend transformations to match the
backend behavior and apply the same change to the additional filename
construction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 636d2ac9-d944-49e3-82f1-9c709cc7b422

📥 Commits

Reviewing files that changed from the base of the PR and between 52f8d8d and 9af22ab.

📒 Files selected for processing (2)
  • app/src/lib/hooks/useHistory.ts
  • backend/routes/history.py

@jamiepine
jamiepine merged commit 1ba935e into jamiepine:main Jul 27, 2026
1 check 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.

2 participants