Repository navigation
Conversation
…parallel message ops - C1: Replace fixed RECONNECT_DELAY=3000 with exponential backoff (3s→6s→12s→24s→48s→60s cap, ±1s jitter); reset to 3s on connect. Drops idle wakeups from ~20/min to ~1/min within 2 minutes of bridge absence. - M3: Add browser.idle.onStateChanged listener for macOS sleep/wake. On system wake (state→'active'), reset backoff and reconnect immediately rather than waiting out the full exponential delay. Add 'idle' permission to manifest.json. - H1: Parallelize read-batch with Promise.all; each message's get()+getFull() also run concurrently — 2N sequential IPC calls → N concurrent pairs. - H2: Parallelize thread reconstruction — all header-ID queries issued concurrently via Promise.all; O(1) Set deduplication replaces O(n) find(). - H3/H4: Add concurrentMap(concurrency=8) helper; replace serial per-message loops in bulk/tag, bulk/fetch, and messages/fetch folder path with it. - docs: Update ENERGY_AUDIT_MACOS25.md with implementation status, updated compliance matrix, and proposed-but-not-implemented M2 (base64 loop) note.
fix(extension): exponential backoff reconnect, sleep/wake awareness, parallel message ops
…L cache Co-authored-by: le-dawg <3172733+le-dawg@users.noreply.github.com>
Fixed 1 file(s) based on 1 unresolved review comment. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Fix extension reconnect/resume regressions and add folder-info TTL cache
Fixed 8 file(s) based on 6 unresolved review comments. Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
fix: harden Thunderbird MCP lifecycle and search failures
…t timeout overrides
Owner
|
Thank you @le-dawg — parts of this ship in 1.1.0 via #25, with you as co-author:
Not taken, with reasons:
Closing in favour of #25. |
jctots
pushed a commit
to jctots/thunderbird-cli
that referenced
this pull request
Sep 14, 2026
…; add heartbeat
A web page in the user's browser could drive the localhost bridge:
- Blind cross-origin POSTs executed even though CORS hid the response
(verified: a text/plain POST /compose {send:true} from
Origin: https://evil.example reached the extension).
- DNS rebinding let a hostile domain read responses same-origin.
- Any page could open ws://127.0.0.1:7701 and replace the extension
socket, receiving every CLI request and answering with forged data.
The bridge now rejects HTTP requests with an Origin outside
TB_BRIDGE_CORS_ORIGINS, Host headers that are not an IP literal,
localhost, *.localhost, *.internal (host.docker.internal) or listed in
TB_BRIDGE_ALLOWED_HOSTS, and WebSocket handshakes from http(s)/file/null
origins. tb, tb-mcp and curl send no Origin header and are unaffected;
the extension connects from moz-extension://.
The CORS allowlist and WebSocket ping/pong heartbeat (drops sockets that
stop answering, e.g. after sleep) come from PR vitalio-sh#20.
test/bridge-security.mjs runs the real bridge: 27 checks, 16 of which
fail against the previous bridge.
Co-authored-by: le-dawg <3172733+le-dawg@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019uoUWTHVsDJpMJCVNFZz5L
jctots
pushed a commit
to jctots/thunderbird-cli
that referenced
this pull request
Sep 14, 2026
… bounded parallelism Integrates the extension parts of PR vitalio-sh#4 and PR vitalio-sh#20, with fixes: Thread (from vitalio-sh#4) - Parse References / In-Reply-To / Message-ID from getRaw() (getFull() doesn't expose them) and strip angle brackets before messages.query({ headerMessageId }) — previously `tb thread` always returned an empty list. getFull() fallback now strips brackets too. - Downstream replies found by subject are limited to exact normalized subject matches (Thunderbird's query is substring), exclude junk, and are labelled threadMatch: "subject" vs "references". - thread-utils.js is loaded by the manifest and is the single source for the parsing helpers instead of a test-only copy. Recent / search (from vitalio-sh#4) - /recent honours accountId, and now unreadOnly as well; the CLI sent both but the extension ignored them. - /messages/search accepts headerMessageId. Connection (from vitalio-sh#20, reworked) - Reconnect backoff 3s → 6s → 12s → 15s cap (PR used 60s, which would leave a restarted bridge waiting up to a minute), reset on connect, immediate retry on idle → active ("idle" permission). - Socket handlers are bound to their own socket, so a late close from a replaced socket can't null the live one (main crashed on ws.send). Throughput (from vitalio-sh#20) - read-batch, fetch, bulk tag/fetch and thread lookups run through a shared queue capped at 8 concurrent operations, preserving order. - Attachment base64 encoded in 32 KB chunks instead of byte by byte. Not taken from vitalio-sh#20: the 30s folder-info cache (stale unread counts right after mark-read; Thunderbird is the source of truth), the /debug/compose-capabilities endpoint, and the 15s resume-poll interval. test/extension.test.mjs loads the real background scripts in a vm with a mocked messenger API (39 checks); against the previous extension the thread, recent, search and reconnect checks fail. Co-authored-by: Daniel Böckenhoff <dboe@ipp.mpg.de> Co-authored-by: le-dawg <3172733+le-dawg@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uoUWTHVsDJpMJCVNFZz5L
jctots
pushed a commit
to jctots/thunderbird-cli
that referenced
this pull request
Sep 14, 2026
…egration email_search no longer requires `query` when at least one filter is given (from PR vitalio-sh#20); with neither it fails with INVALID_ARGS instead of running an unbounded search. Not taken from PR vitalio-sh#20's client changes: the per-call /bridge/status preflight (the bridge already answers 503 immediately when the extension is disconnected), the new SEARCH_UNHEALTHY / LIST_UNHEALTHY codes and `timeout !== 30000` override heuristic (error-code contract change whose docs disagreed with the code), and error mapping that dropped the bridge's own `code` (it would have hidden AUTH_REQUIRED from vitalio-sh#21). Co-authored-by: le-dawg <3172733+le-dawg@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uoUWTHVsDJpMJCVNFZz5L
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR improves runtime resilience and macOS (on Apple Silicon) energy consumption across the extension and bridge.
The main changes:
What changed
Extension
browser.idleidlepermission required for idle-state reconnect handlingBridge
Why
Batterymaxxing.
Testing
Please run before merge:
npm test npm run test:mcpChecklist
✅ Runtime behavior improved in extension and bridge
✅ Docs updated for the new behavior/audit
✅ Test suites run locally before merge