feat: add sitecustomize import hook
This commit is contained in:
parent
a342e3fcec
commit
436104b944
91
sitecustomize_hook.py
Normal file
91
sitecustomize_hook.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
"""
|
||||||
|
sitecustomize hook — Claude Code OAuth bypass for hermes-agent.
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
This file is installed into the hermes-agent venv's site-packages as
|
||||||
|
``sitecustomize.py`` by ``install.sh``. It runs once at Python interpreter
|
||||||
|
startup (before any user code) and hooks the import of
|
||||||
|
``agent.anthropic_adapter`` so that the billing bypass patch is applied
|
||||||
|
immediately after the module loads.
|
||||||
|
|
||||||
|
To disable: run ``uninstall.sh`` or delete the sitecustomize.py from the
|
||||||
|
venv's site-packages and restart hermes-gateway.
|
||||||
|
|
||||||
|
DO NOT EDIT THIS FILE IN THE VENV — it will be overwritten on next install.
|
||||||
|
Edit the source in the hermes-claude-auth repo instead.
|
||||||
|
"""
|
||||||
|
# hermes-claude-auth managed — do not remove this marker
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
_PATCHES_DIR = os.environ.get(
|
||||||
|
"HERMES_PATCHES_DIR",
|
||||||
|
os.path.expanduser("~/.hermes/patches"),
|
||||||
|
)
|
||||||
|
_TARGET_MODULE = "agent.anthropic_adapter"
|
||||||
|
|
||||||
|
if os.path.isdir(_PATCHES_DIR) and _PATCHES_DIR not in sys.path:
|
||||||
|
sys.path.insert(0, _PATCHES_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
def _install_hook() -> None:
|
||||||
|
try:
|
||||||
|
from importlib.abc import MetaPathFinder
|
||||||
|
from importlib.util import find_spec
|
||||||
|
except ImportError:
|
||||||
|
return
|
||||||
|
|
||||||
|
class _ClaudeCodeBypassFinder(MetaPathFinder):
|
||||||
|
_patched = False
|
||||||
|
|
||||||
|
def find_spec(self, fullname, path=None, target=None): # type: ignore[override]
|
||||||
|
if fullname != _TARGET_MODULE or self._patched:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Temporarily remove ourselves to avoid recursion during find_spec.
|
||||||
|
if self in sys.meta_path:
|
||||||
|
sys.meta_path.remove(self)
|
||||||
|
try:
|
||||||
|
spec = find_spec(fullname)
|
||||||
|
finally:
|
||||||
|
if self not in sys.meta_path:
|
||||||
|
sys.meta_path.insert(0, self)
|
||||||
|
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
original_exec = getattr(spec.loader, "exec_module", None)
|
||||||
|
if not callable(original_exec):
|
||||||
|
return None
|
||||||
|
|
||||||
|
finder = self
|
||||||
|
|
||||||
|
def patched_exec(module): # type: ignore[no-untyped-def]
|
||||||
|
original_exec(module)
|
||||||
|
finder._patched = True
|
||||||
|
try:
|
||||||
|
import anthropic_billing_bypass
|
||||||
|
|
||||||
|
anthropic_billing_bypass.apply_patches(module)
|
||||||
|
except Exception as exc:
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
sys.stderr.write(
|
||||||
|
f"[hermes-claude-auth] bypass failed: "
|
||||||
|
f"{type(exc).__name__}: {exc}\n"
|
||||||
|
)
|
||||||
|
traceback.print_exc(file=sys.stderr)
|
||||||
|
|
||||||
|
spec.loader.exec_module = patched_exec # type: ignore[attr-defined]
|
||||||
|
return spec
|
||||||
|
|
||||||
|
sys.meta_path.insert(0, _ClaudeCodeBypassFinder())
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
_install_hook()
|
||||||
|
except Exception as _exc:
|
||||||
|
sys.stderr.write(f"[hermes-claude-auth] hook install failed: {_exc}\n")
|
||||||
Loading…
x
Reference in New Issue
Block a user