Skip to content

fix(whatsapp): resolve bridge dir with HERMES_HOME mirror in read-only Docker (fix #49561) - #49839

Merged
teknium1 merged 2 commits into
mainfrom
hermes/whatsapp-bridge-fix
Jun 21, 2026
Merged

fix(whatsapp): resolve bridge dir with HERMES_HOME mirror in read-only Docker (fix #49561)#49839
teknium1 merged 2 commits into
mainfrom
hermes/whatsapp-bridge-fix

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Fixes the v0.17.0 regression where the WhatsApp bridge cannot be installed in the Docker image. In Docker the install tree (/opt/hermes) is read-only, so npm install for the bridge fails with EACCES: permission denied, mkdir /opt/hermes/scripts/whatsapp-bridge/node_modules.

Salvages #49654 by @xydigit-zt (Zheng Tao). The PR's base was 41 commits behind main and the WhatsApp adapter had since been migrated from gateway/platforms/whatsapp.py to plugins/platforms/whatsapp/adapter.py, so the change was re-applied onto current main.

Changes

  • gateway/platforms/whatsapp_common.py: new shared resolve_whatsapp_bridge_dir() — if the install dir is read-only, mirror the bridge source into a writable HERMES_HOME location and return that path.
  • plugins/platforms/whatsapp/adapter.py: adapter resolves _DEFAULT_BRIDGE_DIR via the shared helper.
  • hermes_cli/main.py: hermes whatsapp install path uses the same helper, so the CLI install and gateway runtime agree on one directory.
  • tests/gateway/test_whatsapp_bridge_dir_resolution.py: writable passthrough, read-only mirror, and existing-mirror-reuse cases.
  • scripts/release.py: AUTHOR_MAP entry for the contributor.

Validation

Before After
Read-only install (/opt/hermes) npm install → EACCES bridge mirrored to writable HERMES_HOME, install succeeds
Writable install works works (returns install dir unchanged)
Existing mirror w/ node_modules n/a reused, not re-copied

Targeted tests: 3/3 new + 40/40 existing WhatsApp tests green. E2E with a real read-only dir (non-root, no mocks) confirmed the mirror is created and populated, and a second call reuses it without clobbering node_modules.

Closes #49561. Supersedes #49654 (cherry-picked with @xydigit-zt's authorship preserved).

Infographic

whatsapp-bridge-readonly-docker-fix

xydigit-zt and others added 2 commits June 20, 2026 15:11
In Docker the install tree (/opt/hermes) is read-only, so npm install for
the WhatsApp bridge fails with EACCES. Add resolve_whatsapp_bridge_dir() in
whatsapp_common.py: when the install dir is read-only, mirror the bridge
source into a writable HERMES_HOME location and use that. Both the
adapter and the 'hermes whatsapp' CLI resolve through the shared helper so
the install and runtime paths agree.

Fixes #49561
Follow-up for salvaged #49654: unit tests for resolve_whatsapp_bridge_dir()
(writable passthrough, read-only mirror, existing-mirror reuse) and the
AUTHOR_MAP entry for the contributor.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/whatsapp-bridge-fix vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11280 on HEAD, 11279 on base (🆕 +1)

🆕 New issues (4):

Rule Count
unresolved-import 1
unsupported-operator 1
unresolved-reference 1
invalid-assignment 1
First entries
tests/gateway/test_whatsapp_bridge_dir_resolution.py:11: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
plugins/platforms/whatsapp/adapter.py:277: [unsupported-operator] unsupported-operator: Operator `/` is not supported between objects of type `None | Unknown` and `Literal["bridge.js"]`
gateway/platforms/whatsapp_common.py:374: [unresolved-reference] unresolved-reference: Name `Path` used when not defined
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

✅ Fixed issues (2):

Rule Count
unresolved-attribute 2
First entries
run_agent.py:2984: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`

Unchanged: 5909 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/whatsapp WhatsApp Business adapter area/docker Docker image, Compose, packaging labels Jun 20, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related: #49654 (original by @xydigit-zt, salvaged here onto current main after the WhatsApp adapter migrated to plugins/platforms/whatsapp/adapter.py), #49561 (the read-only Docker bridge-install regression this fixes). This is the authoritative re-application, not a duplicate.

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

Labels

area/docker Docker image, Compose, packaging comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/whatsapp WhatsApp Business adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Regression - WhatsApp bridge cannot be installed

3 participants