Skip to content

Add idle memory recycling and improve bridge error handling#2

Merged
htlin222 merged 1 commit into
mainfrom
claude/affectionate-planck-bvajrv
Jun 21, 2026
Merged

Add idle memory recycling and improve bridge error handling#2
htlin222 merged 1 commit into
mainfrom
claude/affectionate-planck-bvajrv

Conversation

@htlin222

Copy link
Copy Markdown
Owner

Summary

This PR improves memory management for the ChatGPT bridge by implementing idle-based page recycling, enhances error handling during navigation failures, and fixes a potential file leak in audio recording.

Key Changes

  • Idle Memory Recycling: Added recycleIfIdle() method to the ChatGPTBridge that reloads the WebView after extended idle periods (default 600s). This bounds memory growth from ChatGPT's SPA which doesn't free accumulated state. The recycling is gated to only occur when the app is truly idle and never interrupts in-flight requests. Cookies persist in the data store, keeping the user logged in.

  • Bridge Error Handling: Extracted waiter resumption logic into a new resumeWaiters() method and added two new WKNavigationDelegate methods (didFail and didFailProvisionalNavigation) to ensure continuations are properly resumed even when navigation fails. This prevents leaks of captured state and hanging in warmBridge().

  • Activity Tracking: Added lastActivity and lastReload timestamps to track bridge usage and reload timing, enabling the idle detection logic.

  • AppState Integration: Integrated recycleIfIdle() calls into the AppState's periodic update loop, gated to only run for ChatGPT provider when not busy or recording.

  • Audio Recording Cleanup: Fixed a potential file leak in AudioRecorder by cleaning up the audio file on disk if AVAudioRecorder.record() fails to start.

Implementation Details

  • The idle recycling is conservative: it requires both idle time thresholds to be exceeded before reloading, and it clears the cached token to force re-authentication on next use.
  • Activity timestamps are updated at the start of transcribe and cleanup operations to accurately reflect when the bridge is in use.
  • The waiter resumption is now centralized and called from both successful initialization and error paths, ensuring no continuations leak.

https://claude.ai/code/session_01EX2M2f8iwWxJMxm68Hj63F

The ChatGPT-Web provider's hidden WKWebView runs ChatGPT's SPA for the
life of the app and never reloads, so its WebContent process grows
unbounded across dictations (each one marshals a base64 audio payload
through callAsyncJavaScript). Reclaim that memory by reloading the warmed
page after a long idle stretch; the reload self-gates on idle time and
never interrupts an in-flight request. Cookies persist in the data store,
so the page stays logged in.

Also add didFail/didFailProvisionalNavigation handlers: without them, a
failed navigation left every task parked in waitUntilReady() unresumed,
leaking those continuations and hanging warmBridge.

Finally, remove the orphaned temp .m4a when AVAudioRecorder.record() fails.
@htlin222
htlin222 merged commit d103b76 into main Jun 21, 2026
2 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.

2 participants