9c9e7ab6e5
Under gateway.multiplex_profiles a secondary profile's turn ran with the LAUNCH profile's working directory, command allowlist, redact_secrets switch, credential file mounts, browser engine/headed flags, LSP service, auxiliary-provider health marks and MCP stderr log, and several TERMINAL_ENV consumers read the process env instead of the routed profile's terminal scope. A standalone `hermes -p X gateway run` never behaved that way. - tools/terminal_scope.py: resolve the terminal.cwd placeholder inside the profile scope with the same rule gateway/run.py applies at import (local -> $HOME, sandbox default otherwise) so the system prompt, context files and the terminal of a routed turn start where the profile's standalone gateway would. - tools/image_source.py, credential_files.py, image_generation_tool.py, skills_tool.py, delegate_tool_progress.py, agent/tool_executor.py: read TERMINAL_ENV / TERMINAL_CWD through the terminal scope. - tools/approval.py (+ approval_floors.py): one permanent allowlist per routed profile home; the unscoped module set stays for single-profile processes. - agent/redact.py: `_redact_enabled()` resolves security.redact_secrets for the routed profile (scope .env, then config); launch snapshot kept when unscoped. - tools/credential_files.py, agent/auxiliary_health.py, agent/lsp/__init__.py, tools/browser_tool_cloud.py, tools/mcp_tool_config.py, tools/tool_result_storage.py: key process caches by profile home (or bypass the slot under an override). Tests: tests/tools/test_multiplex_turn_parity.py (4, red on base). Docs: multi-profile-gateways.md isolation table.
41 lines
1.8 KiB
Python
41 lines
1.8 KiB
Python
"""Endpoint identity for auxiliary custom-provider health checks."""
|
|
import contextlib
|
|
from typing import Any, Optional
|
|
|
|
from hermes_cli.route_identity import normalize_route_base_url
|
|
|
|
def _unhealthy_cache_key(provider: str, base_url: Optional[str] = None) -> Any:
|
|
"""Provider-wide key, or endpoint-specific key for an explicit custom endpoint — prefixed with the
|
|
active profile home: a 402 on profile A's account must not hide the provider from profile B's
|
|
(differently funded) account in the same multiplexed process."""
|
|
from agent.auxiliary_client import _normalize_chain_label
|
|
from hermes_constants import hermes_home_key
|
|
label = _normalize_chain_label(provider)
|
|
endpoint = normalize_route_base_url(_custom_health_base_url(provider, base_url))
|
|
home_key = hermes_home_key()
|
|
if endpoint:
|
|
return home_key, "custom-endpoint", endpoint
|
|
return home_key, label
|
|
|
|
|
|
def _custom_health_base_url(provider: str, explicit_base_url: Optional[str] = None) -> str:
|
|
"""Return the concrete custom endpoint used to scope health and failed-route checks."""
|
|
from agent.auxiliary_client import _current_custom_base_url
|
|
explicit = str(explicit_base_url or "").strip()
|
|
from agent.auxiliary_client import _normalize_chain_label
|
|
label = _normalize_chain_label(provider)
|
|
if label == "local/custom":
|
|
return explicit or _current_custom_base_url()
|
|
if label.startswith("custom:") and explicit:
|
|
return explicit
|
|
with contextlib.suppress(ImportError):
|
|
from hermes_cli.runtime_provider import _get_named_custom_provider, _resolves_to_custom
|
|
if _resolves_to_custom(label):
|
|
return explicit or _current_custom_base_url()
|
|
entry = _get_named_custom_provider(provider)
|
|
if entry:
|
|
return explicit or str(entry.get("base_url") or "").strip()
|
|
return ""
|
|
|
|
|