Skip to content

🔊 fix: Clear TTS Audio Cache On Session End and Hash Its Keys - #16998

Open
berry-13 wants to merge 30 commits into
berry-13/plugin-auth-encrypt-v3from
berry-13/tts-cache-cleanup
Open

berry-13 wants to merge 30 commits into
berry-13/plugin-auth-encrypt-v3from
berry-13/tts-cache-cleanup

Conversation

@berry-13

@berry-13 berry-13 commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

With cacheTTS on (the default), auto-played and external TTS persisted audio to Cache Storage (tts-responses) keyed by the full assistant message text, and no logout or account-switch path cleared it. On a shared browser the next user could read previous replies, and play the audio, from DevTools.

Read-aloud audio is now cached only in the tab's memory: a small map (50 recordings or 32 MB, least recently used evicted) keyed by a SHA-256 hash of the user id, voice and spoken text, so nothing reaches disk, one account can never match another's audio, and the cache dies with the tab. Every session end empties it (logout, IdP logout, a failed logout, a rejected or empty token refresh, a failed user query, and signing in as a different account without a logout), as does the Settings "delete cache" action; a generation counter keeps a request that was in flight across a logout from writing afterwards. The tts-responses cache that earlier versions left on disk is deleted at app startup, on logout and on the Settings clear. The voice is part of the key, so changing voice no longer replays audio from the old one.

Stacked on #16997.

Type of change

  • Bug fix

Testing

Tested environments/configuration:

  • cacheTTS on, external TTS engine (routed in the e2e harness), desktop light, desktop dark and mobile.

Automated tests:

  • client/src/utils/ttscache.spec.ts (hash key, user isolation, hit and miss, count and size eviction, clear, account switch, generation fence, legacy cache delete guarded), one AuthContext.spec.tsx test per session-end path, and StreamAudio.spec.tsx (lookup by the spoken answer): all pass.
  • e2e/specs/mock/scenarios/tts-cache.spec.ts: a replay plays without a second TTS request, Cache Storage never holds TTS audio, logout empties the cache in the same tab, and a legacy tts-responses cache is deleted at startup. All four pass in desktop light, desktop dark and mobile.
  • ESLint, Prettier, import order and the client typecheck on changed files: clean.

Screenshots / recordings

No user-facing change

Risk / compatibility

Cached audio no longer survives a reload or carries over to other tabs, so replaying a message after a reload, in another tab, or after signing back in regenerates the audio (one more TTS request). Per-conversation eviction on delete is not included.

Checklist

  • I reviewed my own changes
  • Relevant tests have been added or updated
  • Existing relevant tests pass
  • The change does not introduce new warnings or errors
  • Required documentation PR: N/A

@berry-13 berry-13 changed the title berry-13/tts-cache-cleanup 🔊 fix: Clear TTS Audio Cache On Session End and Hash Its Keys Oct 11, 2026
@berry-13
berry-13 marked this pull request as ready for review October 11, 2026 22:20
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T12:51:03.676695Z ff97e0d New commits
🔒 Security Review ✅ Completed 2026-10-11T22:22:59.490625Z a206972 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a20697241f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/hooks/AuthContext.tsx

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90cb311faa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 21fc282bf1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/AuthContext.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a8325cef2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e961b274b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cd0f270fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4591fc1e5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46514ac3b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3d1d11cfe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/AuthContext.tsx Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: de4d516899

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9cb21fb2cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/AuthContext.tsx Outdated
Comment thread client/src/utils/ttscache.ts Outdated
Comment thread client/src/utils/ttscache.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4601b30d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

/** Earlier versions persisted read-aloud audio to Cache Storage under this name, keyed by the
* message text. Audio is now held only in this tab's memory, so that cache is just deleted. */
const LEGACY_TTS_CACHE_NAME = 'tts-responses';
const MAX_ENTRIES = 50;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound the in-memory cache by audio size

When caching is enabled for long responses, this 50-entry limit can retain hundreds of megabytes because each entry is a complete Blob and there is no byte budget; the manual TTS path even accepts and chunks inputs beyond 4096 characters. On memory-constrained browsers this can trigger tab eviction or an out-of-memory failure despite the apparent cap. Track total blob bytes and evict against a configurable memory limit rather than bounding only the number of recordings.

AGENTS.md reference: AGENTS.md:L91-L93

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 571486e: the in-memory cache is now bounded at 32 MB of audio as well as 50 recordings (least recently used evicted), and a single recording over the budget is not kept; ttscache.spec covers both. Making the limits configurable is tracked at berry-13#326.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

if (!browserSupportsType) {
setGlobalAudioURL(URL.createObjectURL(audioBlob));

P1 Badge Drop streamed audio after the session generation changes

In a browser without MSE support, such as Safari, a TTS response that remains pending across a same-document logout and login still reaches this unconditional setter. Logout clears the atom and increments generation, but the effect neither aborts its fetch on unmount nor checks that generation before publishing the completed blob; the stale Recoil setter can therefore repopulate globalAudioURL after the next account signs in, causing its mounted autoplay element to play the departing account's audio. The fresh evidence beyond the obsolete persistent-cache threads is that this final in-memory implementation fences only setCachedTTSAudio, not response consumption; abort the stream or check the captured generation before publishing audio.

AGENTS.md reference: AGENTS.md:L45-L48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20b55700e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +25 to +26
const checkCache = useCallback(() => {
setIsCacheEmpty(!hasCachedTTSAudio());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the delete action available for retained legacy caches

If the startup clearTTSCache() attempt fails to delete an earlier build's tts-responses cache, this check reports the cache as empty because it inspects only the new in-memory map. The button is then disabled even though the legacy cache can still contain plaintext assistant messages; before this change, the Settings check inspected that persistent cache and allowed the user to retry deletion. Include the legacy Cache Storage state or a failed-cleanup marker when determining whether deletion is available.

AGENTS.md reference: AGENTS.md:L45-L48

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 858b67c and de1bd9c: the Settings check also reports a legacy cache still on disk (an unreadable check counts as present), and after a delete it rechecks once the legacy deletes settle, so a failed removal keeps the action available; DeleteCache.test covers both and fails on 20b5570.

Base automatically changed from berry-13/sharepoint-picker-logs to berry-13/plugin-auth-encrypt-v3 October 12, 2026 08:51
@berry-13
berry-13 force-pushed the berry-13/tts-cache-cleanup branch from 8a0a4ec to f957159 Compare October 12, 2026 12:12
@berry-13
berry-13 force-pushed the berry-13/plugin-auth-encrypt-v3 branch from b7016bf to c97c988 Compare October 12, 2026 12:12
@github-actions

Copy link
Copy Markdown
Contributor

Lighthouse CI failed. The last 80 log lines contain the measured budgets and assertion failures.


[WebServer] 2026-10-12 12:14:10 info: [StreamServices] Created in-memory stream services

[WebServer] 2026-10-12 12:14:10 info: [GenerationJobManager] Configured with in-memory stores

[WebServer] 2026-10-12 12:14:10 info: HTTP server timeout configuration

[WebServer] 2026-10-12 12:14:10 info: Server listening at http://localhost:3080

[WebServer] 2026-10-12 12:14:10 info: [MCPServersRegistry] Creating new instance

[WebServer] 2026-10-12 12:14:10 info: OAuth reconnect manager initialized successfully.

[WebServer] 2026-10-12 12:14:10 info: Created collection: projects

🤖: global setup has been started
🤖: using baseURL http://localhost:3080
🤖: using E2E user: testuser@example.com
[WebServer] 2026-10-12 12:14:12 info: [agent-triggers] durable delivery engine started

[WebServer] 2026-10-12 12:14:13 info: [schedules] engine started

[WebServer] 2026-10-12 12:14:13 info: Server readiness checks passing.

🤖: 🗝  authenticating user: testuser@example.com
🤖: ✔️  localStorage: set Nav as Visible /home/runner/work/LibreChat/LibreChat/e2e/storageState.json
🤖: ✔️  user successfully registered
[WebServer] 2026-10-12 12:14:22 info: [Login] [Login successful] [Username: testuser@example.com] [Request-IP: ::1] {"requestId":"032e7897-6ab5-45fa-90ed-b9879e564b3b","request_id":"032e7897-6ab5-45fa-90ed-b9879e564b3b","request_method":"POST","request_path":"/api/auth"}

🤖: ✔️  user successfully authenticated
🤖: ✔️  authentication state successfully saved in /home/runner/work/LibreChat/LibreChat/e2e/storageState.json
🤖: global setup has been finished

Running 1 test using 1 worker

[1/1] [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets
[chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets
Lighthouse run 1/3 wrote /home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-1.report.json

Lighthouse run 2/3 attempt 1 did not complete, retrying: Command failed: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/runner/work/LibreChat/LibreChat/node_modules/lighthouse/cli/index.js http://localhost:3080/c/16390000-0000-4000-8000-000000000001 --quiet --preset=desktop --throttling-method=provided --only-categories=performance --chrome-flags=--headless=new --extra-headers={"Cookie":"token_provider=librechat; refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjZhY2NjZjFhZGIwOTcwNjFjNzg3NjBlNSIsInNlc3Npb25JZCI6IjZhY2NjZjIxZGIwOTcwNjFjNzg3NjEwNSIsImlzc3VlZEF0TXMiOjE3OTE4MDcyNjU3NjAsImlhdCI6MTc5MTgwNzI2NSwiZXhwIjoxNzkxODEwODY1fQ.R7IR6pXY0jnJyhVHwTtGpITWl97NRkQplBTAGwQxjmA"} --output=json --output=html --output-path=/home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-2

  1) [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets 

    Error: Command failed: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/runner/work/LibreChat/LibreChat/node_modules/lighthouse/cli/index.js http://localhost:3080/c/16390000-0000-4000-8000-000000000001 --quiet --preset=desktop --throttling-method=provided --only-categories=performance --chrome-flags=--headless=new --extra-headers={"Cookie":"token_provider=librechat; refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjZhY2NjZjFhZGIwOTcwNjFjNzg3NjBlNSIsInNlc3Npb25JZCI6IjZhY2NjZjIxZGIwOTcwNjFjNzg3NjEwNSIsImlzc3VlZEF0TXMiOjE3OTE4MDcyNjU3NjAsImlhdCI6MTc5MTgwNzI2NSwiZXhwIjoxNzkxODEwODY1fQ.R7IR6pXY0jnJyhVHwTtGpITWl97NRkQplBTAGwQxjmA"} --output=json --output=html --output-path=/home/runner/work/LibreChat/LibreChat/.lighthouse/lhr-2
    Runtime error encountered: Something went wrong with recording the trace over your page load. Please run Lighthouse again. (NO_NAVSTART)


    attachment #1: screenshot (image/png) ──────────────────────────────────────────────────────────
    e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/test-failed-1.png
    ────────────────────────────────────────────────────────────────────────────────────────────────

    Error Context: e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/error-context.md

    attachment #3: trace (application/zip) ─────────────────────────────────────────────────────────
    e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/trace.zip
    Usage:

        npx playwright show-trace e2e/lighthouse/.test-results/load-serial-database-latency-stays-within-web-vitals-budgets-chrome/trace.zip

    ────────────────────────────────────────────────────────────────────────────────────────────────


🤖: global teardown has been started
2026-10-12 12:16:10 �[32minfo�[39m: �[32mMongo Connection options�[39m
2026-10-12 12:16:10 �[32minfo�[39m: �[32m{�[39m
�[32m  "bufferCommands": false�[39m
�[32m}�[39m
🤖:  ✅  Connected to Database
🤖:  ✅  Found user in Database
🤖:  ✅  Deleted 1 convos & 2 messages
🤖:  ✅  Deleted user from Database
🤖: global teardown has been started
2026-10-12 12:16:11 �[32minfo�[39m: �[32mMongo Connection options�[39m
2026-10-12 12:16:11 �[32minfo�[39m: �[32m{�[39m
�[32m  "bufferCommands": false�[39m
�[32m}�[39m
🤖:  ✅  Connected to Database
🤖:  ⚠️  User not found in Database
  1 failed
    [chrome] › e2e/lighthouse/load.spec.ts:10:5 › serial database latency stays within web-vitals budgets 

Open the full run

@berry-13
berry-13 force-pushed the berry-13/tts-cache-cleanup branch from f957159 to ff97e0d Compare October 12, 2026 12:44

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant