simplify(compat): plugins/memory — drop 15 re-exports + 1 alias, repoint 13 test callers
hindsight: drop _PORT_HEALTH_GRACE_ENV/_sanitize_bank_segment facade re-exports (tests -> .embedded/.settings). honcho: drop 5 tool-schema re-exports, _credential_fingerprint (-> client_cache), _is_auth_error (-> session_auth), and the _redact_tokens alias (callers renamed to redact_tokens). openviking: drop 5 _setup re-exports; tests call openviking_module._setup.* directly.
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
"""Compatibility shim — the real implementation is ``hermes_startup_watchdog``.
|
||||
|
||||
The startup-liveness watchdog must be armable *before* the ``gateway`` package
|
||||
is imported (``gateway/__init__`` eagerly pulls in the config/session/delivery
|
||||
graph, and an import-time deadlock is inside the watchdog's coverage mandate),
|
||||
so the implementation lives at the repository top level as a stdlib-only
|
||||
module. This shim keeps ``gateway.startup_watchdog`` importable for code that
|
||||
runs after the package is loaded (the disarm site in ``gateway.run``, tests).
|
||||
"""
|
||||
|
||||
from hermes_startup_watchdog import ( # noqa: F401
|
||||
DEFAULT_STARTUP_WATCHDOG_TIMEOUT_S,
|
||||
ENV_STARTUP_WATCHDOG,
|
||||
ENV_STARTUP_WATCHDOG_TIMEOUT_S,
|
||||
SERVICE_RESTART_EXIT_CODE,
|
||||
StartupWatchdogHandle,
|
||||
arm_startup_watchdog,
|
||||
disarm_startup_watchdog,
|
||||
get_startup_watchdog_dump_path,
|
||||
kick_startup_watchdog,
|
||||
report_startup_progress,
|
||||
resolve_startup_watchdog_timeout,
|
||||
startup_watchdog_disabled,
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
"""Compatibility alias for the core Hermes Relay runtime."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from agent import relay_runtime as _core_relay_runtime
|
||||
|
||||
sys.modules[__name__] = _core_relay_runtime
|
||||
@@ -32,18 +32,17 @@ from hermes_constants import get_hermes_home
|
||||
from hermes_time import now as _hermes_now
|
||||
from tools.registry import tool_error
|
||||
|
||||
# Re-exported (tests patch/import these via this module).
|
||||
from .embedded import ( # noqa: F401
|
||||
_PORT_HEALTH_GRACE_ENV, _RETRIABLE_CONNECTION_MARKERS, _build_embedded_profile_env,
|
||||
from .embedded import (
|
||||
_RETRIABLE_CONNECTION_MARKERS, _build_embedded_profile_env,
|
||||
_check_local_runtime, _embedded_llm_api_key, _embedded_profile_env_path,
|
||||
_export_port_health_grace_timeout, _load_simple_env, _local_runtime_hint, _materialize_embedded_profile_env,
|
||||
)
|
||||
from .settings import ( # noqa: F401
|
||||
from .settings import (
|
||||
_DEFAULT_API_URL, _DEFAULT_IDLE_TIMEOUT, _DEFAULT_LOCAL_URL, _DEFAULT_RETAIN_SOURCE,
|
||||
_DEFAULT_TIMEOUT, _HINDSIGHT_GLYPH, _MIN_CLIENT_VERSION, _MIN_VERSION_FOR_UPDATE_MODE_APPEND,
|
||||
_PROVIDER_DEFAULT_MODELS, _VALID_BUDGETS, _daemon_llm_provider,
|
||||
_normalize_observation_scopes, _normalize_retain_tags, _parse_int_setting,
|
||||
_resolve_bank_id_template, _sanitize_bank_segment,
|
||||
_resolve_bank_id_template,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -19,9 +19,7 @@ from agent.memory_manager import sanitize_context
|
||||
from agent.memory_provider import MemoryProvider, is_trivial_prompt
|
||||
from plugins.memory.honcho.client import spawn_context_thread
|
||||
from plugins.memory.honcho.dialectic import DialecticMixin
|
||||
from plugins.memory.honcho.tool_schemas import ( # noqa: F401 — re-exported
|
||||
ALL_TOOL_SCHEMAS, CONCLUDE_SCHEMA, CONTEXT_SCHEMA, PROFILE_SCHEMA, REASONING_SCHEMA, SEARCH_SCHEMA,
|
||||
)
|
||||
from plugins.memory.honcho.tool_schemas import ALL_TOOL_SCHEMAS
|
||||
from tools.registry import tool_error
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -27,10 +27,8 @@ from agent.secret_scope import get_secret
|
||||
from hermes_cli.profiles import _get_default_hermes_home
|
||||
from hermes_constants import get_hermes_home
|
||||
|
||||
# Cache/slot cluster lives in client_cache.py; re-exported because tests and reset
|
||||
# bookkeeping reach these names through this module.
|
||||
from plugins.memory.honcho.client_cache import ( # noqa: F401
|
||||
_DEFAULT_HTTP_TIMEOUT, _client_cache_key, _client_slots, _client_slots_lock, _credential_fingerprint,
|
||||
from plugins.memory.honcho.client_cache import (
|
||||
_DEFAULT_HTTP_TIMEOUT, _client_cache_key, _client_slots, _client_slots_lock,
|
||||
_honcho_json_timeout_memo, _refresh_oauth, _slot_for,
|
||||
)
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ def redact_tokens(text: str) -> str:
|
||||
"""Replace any embedded token values with their prefix plus a placeholder."""
|
||||
return _TOKEN_VALUE_RE.sub(lambda m: f"{m.group(1)}[redacted]", text)
|
||||
|
||||
_redact_tokens = redact_tokens # backward-compat alias for older importers
|
||||
|
||||
class OAuthRefreshError(Exception):
|
||||
"""Token endpoint rejected the refresh. ``permanent`` means re-login is required."""
|
||||
|
||||
@@ -231,7 +229,7 @@ def _exchange_refresh_token(
|
||||
if status >= 400:
|
||||
error, description = str(body.get("error") or ""), str(body.get("error_description") or "")
|
||||
detail = " — ".join(p for p in (error, description) if p) or "no error body"
|
||||
message = _redact_tokens(f"token endpoint returned HTTP {status}: {detail}")
|
||||
message = redact_tokens(f"token endpoint returned HTTP {status}: {detail}")
|
||||
raise OAuthRefreshError(message, error=error, permanent=error in _PERMANENT_OAUTH_ERRORS)
|
||||
return OAuthCredential.from_token_response(
|
||||
body, now=now, client_id=cred.client_id, token_endpoint=cred.token_endpoint,
|
||||
@@ -251,7 +249,7 @@ def _exchange_with_retry(cred: OAuthCredential, *, now: float) -> OAuthCredentia
|
||||
remaining = deadline - time.monotonic() - _REFRESH_RETRY_DELAY_SECONDS
|
||||
if remaining <= 0:
|
||||
raise first
|
||||
logger.warning("Honcho OAuth token exchange failed, retrying once: %s", _redact_tokens(str(first)))
|
||||
logger.warning("Honcho OAuth token exchange failed, retrying once: %s", redact_tokens(str(first)))
|
||||
time.sleep(_REFRESH_RETRY_DELAY_SECONDS)
|
||||
return _exchange_refresh_token(cred, now=now, timeout=min(remaining, _REFRESH_TIMEOUT_SECONDS))
|
||||
|
||||
@@ -269,7 +267,7 @@ def _rotate_and_persist(
|
||||
"run 'hermes honcho setup' to re-authenticate", host, exc)
|
||||
return None
|
||||
_refresh_failure_at[key] = time.monotonic()
|
||||
logger.warning("Honcho OAuth %s failed for host %s: %s", op_label, host, _redact_tokens(str(exc)))
|
||||
logger.warning("Honcho OAuth %s failed for host %s: %s", op_label, host, redact_tokens(str(exc)))
|
||||
return None
|
||||
_persist_credential(path, host, rotated)
|
||||
return rotated
|
||||
|
||||
@@ -11,7 +11,7 @@ from datetime import datetime
|
||||
from typing import Any, TYPE_CHECKING
|
||||
|
||||
from plugins.memory.honcho.client import get_honcho_client, spawn_context_thread
|
||||
from plugins.memory.honcho.session_auth import HonchoAuthError, SessionAuthMixin, _is_auth_error # noqa: F401 — re-exported
|
||||
from plugins.memory.honcho.session_auth import HonchoAuthError, SessionAuthMixin
|
||||
from plugins.memory.honcho.session_context import SessionContextMixin
|
||||
from plugins.memory.honcho.session_migration import SessionMigrationMixin
|
||||
from plugins.memory.honcho.session_peers import SessionPeersMixin
|
||||
|
||||
@@ -1037,13 +1037,6 @@ def _classify_runtime_openviking_health(client: _VikingClient, endpoint: str) ->
|
||||
|
||||
|
||||
from . import _setup # noqa: E402 (needs the helpers above at call time)
|
||||
from ._setup import ( # noqa: E402,F401 re-exported: tests and callers patch these here
|
||||
_SETUP_CANCELLED,
|
||||
_handle_unreachable_endpoint,
|
||||
_link_ovcli_profile,
|
||||
_prompt_manual_connection_values,
|
||||
_save_hermes_only_config,
|
||||
)
|
||||
|
||||
|
||||
# -- MemoryProvider implementation ------------------------------------------
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
"""Descriptor <- PlatformEntry projection (relay Phase 0, Task 0.3).
|
||||
|
||||
Proves the CapabilityDescriptor is a projection of the existing PlatformEntry,
|
||||
not a parallel concept: the entry's label/limit/emoji/hint/pii fields carry
|
||||
straight through.
|
||||
"""
|
||||
|
||||
from gateway.platform_registry import PlatformEntry
|
||||
from gateway.relay.descriptor import CONTRACT_VERSION, CapabilityDescriptor
|
||||
|
||||
|
||||
def _entry(**overrides) -> PlatformEntry:
|
||||
base = dict(
|
||||
name="telegram",
|
||||
label="Telegram",
|
||||
adapter_factory=lambda cfg: None,
|
||||
check_fn=lambda: True,
|
||||
max_message_length=4096,
|
||||
pii_safe=False,
|
||||
emoji="\u2708\ufe0f",
|
||||
platform_hint="You are on Telegram.",
|
||||
)
|
||||
base.update(overrides)
|
||||
return PlatformEntry(**base)
|
||||
|
||||
|
||||
def test_projection_carries_platform_entry_fields():
|
||||
d = CapabilityDescriptor.from_platform_entry(_entry(), len_unit="utf16")
|
||||
assert d.contract_version == CONTRACT_VERSION
|
||||
assert d.platform == "telegram"
|
||||
assert d.label == "Telegram"
|
||||
assert d.max_message_length == 4096
|
||||
assert d.emoji == "\u2708\ufe0f"
|
||||
assert d.platform_hint == "You are on Telegram."
|
||||
assert d.pii_safe is False
|
||||
assert d.len_unit == "utf16"
|
||||
|
||||
|
||||
def test_projection_defaults_for_runtime_bits():
|
||||
# Bits PlatformEntry does not encode take the documented defaults.
|
||||
d = CapabilityDescriptor.from_platform_entry(_entry())
|
||||
assert d.len_unit == "chars"
|
||||
assert d.supports_draft_streaming is False
|
||||
assert d.supports_edit is True
|
||||
assert d.supports_threads is False
|
||||
assert d.markdown_dialect == "plain"
|
||||
|
||||
|
||||
def test_zero_unlimited_length_normalizes_to_chunking_default():
|
||||
# PlatformEntry uses 0 for "no limit"; the descriptor must always carry a
|
||||
# concrete chunking bound (the stream_consumer default of 4096).
|
||||
d = CapabilityDescriptor.from_platform_entry(_entry(max_message_length=0))
|
||||
assert d.max_message_length == 4096
|
||||
@@ -18,8 +18,8 @@ from plugins.memory.honcho.session import (
|
||||
HonchoAuthError,
|
||||
HonchoSession,
|
||||
HonchoSessionManager,
|
||||
_is_auth_error,
|
||||
)
|
||||
from plugins.memory.honcho.session_auth import _is_auth_error
|
||||
|
||||
|
||||
def _host_block(refresh="hch-rt-old", expires_at=100):
|
||||
@@ -154,7 +154,7 @@ class TestExchangeRetry:
|
||||
assert "grant revoked" in caplog.text
|
||||
|
||||
def test_redaction_strips_token_values(self):
|
||||
redacted = oauth._redact_tokens(
|
||||
redacted = oauth.redact_tokens(
|
||||
"exchange failed for hch-rt-supersecret123 got hch-at-alsosecret456"
|
||||
)
|
||||
assert "supersecret123" not in redacted
|
||||
|
||||
@@ -21,6 +21,7 @@ import threading
|
||||
import pytest
|
||||
|
||||
import plugins.memory.honcho.client as client_mod
|
||||
import plugins.memory.honcho.client_cache as client_cache_mod
|
||||
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
|
||||
from plugins.memory.honcho.client import (
|
||||
HonchoClientConfig,
|
||||
@@ -245,12 +246,12 @@ class TestCredentialIdentity:
|
||||
token = set_hermes_home_override(home)
|
||||
try:
|
||||
cfg1 = HonchoClientConfig.from_global_config()
|
||||
fp1 = client_mod._credential_fingerprint(cfg1)
|
||||
fp1 = client_cache_mod._credential_fingerprint(cfg1)
|
||||
|
||||
# Access token rotates in place; refresh token unchanged.
|
||||
cfg_rotated = HonchoClientConfig.from_global_config()
|
||||
cfg_rotated.api_key = "access-token-2"
|
||||
fp_rotated = client_mod._credential_fingerprint(cfg_rotated)
|
||||
fp_rotated = client_cache_mod._credential_fingerprint(cfg_rotated)
|
||||
|
||||
# Re-auth: new refresh token.
|
||||
oauth_block2 = dict(oauth_block, refreshToken="refresh-2")
|
||||
@@ -259,7 +260,7 @@ class TestCredentialIdentity:
|
||||
"oauth": oauth_block2}},
|
||||
}))
|
||||
cfg2 = HonchoClientConfig.from_global_config()
|
||||
fp2 = client_mod._credential_fingerprint(cfg2)
|
||||
fp2 = client_cache_mod._credential_fingerprint(cfg2)
|
||||
finally:
|
||||
reset_hermes_home_override(token)
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ class TestPeerLookupHelpers:
|
||||
class TestConcludeToolDispatch:
|
||||
def test_conclude_schema_has_no_anyof(self):
|
||||
"""anyOf/oneOf/allOf breaks Anthropic and Fireworks APIs — schema must be plain object."""
|
||||
from plugins.memory.honcho import CONCLUDE_SCHEMA
|
||||
from plugins.memory.honcho.tool_schemas import CONCLUDE_SCHEMA
|
||||
params = CONCLUDE_SCHEMA["parameters"]
|
||||
assert params["type"] == "object"
|
||||
assert "conclusion" in params["properties"]
|
||||
|
||||
@@ -32,9 +32,9 @@ from plugins.memory.hindsight import (
|
||||
_normalize_observation_scopes,
|
||||
_normalize_retain_tags,
|
||||
_resolve_bank_id_template,
|
||||
_sanitize_bank_segment,
|
||||
_WRITER_SENTINEL,
|
||||
)
|
||||
from plugins.memory.hindsight.settings import _sanitize_bank_segment
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -192,7 +192,7 @@ def test_hermes_only_save_uses_the_same_clean_values_in_file_and_process(
|
||||
from dotenv import dotenv_values
|
||||
|
||||
env_path = tmp_path / ".env"
|
||||
ov._save_hermes_only_config(
|
||||
ov._setup._save_hermes_only_config(
|
||||
config={"memory": {}},
|
||||
provider_config={},
|
||||
env_path=env_path,
|
||||
@@ -226,7 +226,7 @@ def test_hermes_only_save_failure_leaves_process_environment_unchanged(
|
||||
|
||||
monkeypatch.setattr(ov, "_write_env_vars", fail_write)
|
||||
with pytest.raises(OSError, match="test write failure"):
|
||||
ov._save_hermes_only_config(
|
||||
ov._setup._save_hermes_only_config(
|
||||
config={"memory": {}},
|
||||
provider_config={},
|
||||
env_path=tmp_path / ".env",
|
||||
|
||||
@@ -243,7 +243,7 @@ def test_link_ovcli_profile_removes_stale_inline_config(tmp_path):
|
||||
}
|
||||
ovcli_path = tmp_path / "ovcli.conf.VPS_ROOT"
|
||||
|
||||
openviking_module._link_ovcli_profile(
|
||||
openviking_module._setup._link_ovcli_profile(
|
||||
config=config,
|
||||
provider_config=provider_config,
|
||||
env_path=env_path,
|
||||
@@ -347,7 +347,7 @@ def test_local_setup_recommends_user_api_key_before_unauthenticated_mode(monkeyp
|
||||
return "user-key"
|
||||
raise AssertionError(f"Unexpected prompt: {label}")
|
||||
|
||||
values = openviking_module._prompt_manual_connection_values(
|
||||
values = openviking_module._setup._prompt_manual_connection_values(
|
||||
prompt,
|
||||
select,
|
||||
-1,
|
||||
@@ -611,7 +611,7 @@ def test_handle_unreachable_endpoint_waits_long_enough_after_autostart(monkeypat
|
||||
lambda endpoint, *, timeout_seconds=0: wait_calls.append((endpoint, timeout_seconds)) or True,
|
||||
)
|
||||
|
||||
result = openviking_module._handle_unreachable_endpoint(
|
||||
result = openviking_module._setup._handle_unreachable_endpoint(
|
||||
"http://127.0.0.1:1934",
|
||||
"OpenViking server is not reachable.",
|
||||
lambda *args, **kwargs: 0,
|
||||
|
||||
@@ -13,7 +13,7 @@ import pytest
|
||||
|
||||
hindsight = importlib.import_module("plugins.memory.hindsight")
|
||||
_export = hindsight._export_port_health_grace_timeout
|
||||
_ENV = hindsight._PORT_HEALTH_GRACE_ENV
|
||||
_ENV = importlib.import_module("plugins.memory.hindsight.embedded")._PORT_HEALTH_GRACE_ENV
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
||||
Reference in New Issue
Block a user