Files
hermes-agent/tools
crew-infra ee3d4905fc fix(connectors): export the package surface lazily to stop the import deadlock
`tools/connectors/__init__.py` imported all five of its submodules eagerly, so a
thread importing the package held the package's module lock while reaching for a
submodule that another thread already held. Python 3.14 aborts one of the two
with:

    _frozen_importlib._DeadlockError: deadlock detected by
    _ModuleLock('tools.connectors.tool')

which is the failure in the Group Chat hosted-room worker startup path
(`gateway/run_startup.py::_ensure_hosted_room_worker` -> `import tui_gateway.server`
-> `methods_connectors._install_update_hook` -> `from tools.connectors import
operation`) while the tool registry's discovery scan imports
`tools.connectors.tool` from another thread.

Exporting the cross-package surface through a module-level `__getattr__` (PEP 562)
removes the parent->child edge entirely: the package `__init__` now imports no
submodule, so it cannot hold its lock while waiting for one. Attribute access,
`from tools.connectors import x` and `__all__` are unchanged.

Measured on Python 3.14.7 by racing `import tools.connectors` (3 threads) against
`import tools.connectors.tool` (3 threads), 40 iterations each:

| tree | outcomes |
| --- | --- |
| before | 120 `_DeadlockError`, 0 successes |
| after | 0 `_DeadlockError`, 0 threads left alive, `import tools.connectors` loads no submodule |

Regression tests run in subprocesses so they assert on a pristine `sys.modules`
(`tests/tools/test_connectors_import_deadlock.py`).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
(cherry picked from commit 1803f53b1ed34487ff6a60cdbde915726be21338)
2026-10-03 16:56:51 +05:30
..
…