hermes: distinguish Claude subscription auth

This commit is contained in:
jenkins 2026-08-13 00:12:02 -03:00
parent 24221636b2
commit 65f2120a20
2 changed files with 74 additions and 0 deletions

View File

@ -619,6 +619,72 @@ if source.count(before) != 1:
path.write_text(source.replace(before, after, 1)) path.write_text(source.replace(before, after, 1))
PY PY
# Keep the dashboard's account cards aligned with the managed provider lanes.
# Switchyard receives Claude Code subscription OAuth through the environment;
# that credential must not be presented as a metered Anthropic API key.
RUN python - <<'PY'
from pathlib import Path
path = Path("/opt/hermes/hermes_cli/web_server.py")
source = path.read_text()
registry_before = ''' try:
from hermes_cli.auth import PROVIDER_REGISTRY
env_var_order = PROVIDER_REGISTRY["anthropic"].api_key_env_vars
except (ImportError, KeyError):
pass
'''
registry_after = ''' try:
from hermes_cli.auth import PROVIDER_REGISTRY
env_var_order = PROVIDER_REGISTRY["anthropic"].api_key_env_vars
except (ImportError, KeyError):
pass
# Claude Code subscription OAuth is reported by its dedicated card below.
env_var_order = tuple(
var for var in env_var_order if var != "CLAUDE_CODE_OAUTH_TOKEN"
)
'''
managed_before = ''' try:
from agent.anthropic_adapter import read_claude_code_credentials
creds = read_claude_code_credentials()
'''
managed_after = ''' managed_token = os.getenv("CLAUDE_CODE_OAUTH_TOKEN")
if managed_token:
return {
"logged_in": True,
"source": "managed_claude_code_subscription",
"source_label": "Switchyard-managed Claude Code subscription",
"token_preview": _truncate_token(managed_token),
"expires_at": None,
"has_refresh_token": False,
}
try:
from agent.anthropic_adapter import read_claude_code_credentials
creds = read_claude_code_credentials()
'''
replacements = (
(registry_before, registry_after, "Anthropic credential separation"),
(managed_before, managed_after, "managed Claude Code status"),
('"name": "Anthropic API Key",',
'"name": "Anthropic API / direct OAuth (not used by Switchyard)",',
"Anthropic account label"),
('"name": "Anthropic OAuth: Required Extra Usage Credits to Use Subscription",',
'"name": "Claude Code subscription (Switchyard)",',
"Claude Code account label"),
)
for before, after, label in replacements:
if source.count(before) != 1:
raise SystemExit(
f"Hermes {label} patch context changed: expected 1, "
f"found {source.count(before)}"
)
source = source.replace(before, after, 1)
path.write_text(source)
PY
COPY dockerfiles/hermes-session-migrate.py /opt/hermes/bin/hermes-session-migrate COPY dockerfiles/hermes-session-migrate.py /opt/hermes/bin/hermes-session-migrate
RUN cd /opt/hermes/web \ RUN cd /opt/hermes/web \
@ -641,6 +707,10 @@ RUN cd /opt/hermes/web \
/opt/hermes/gateway/platforms/api_server.py \ /opt/hermes/gateway/platforms/api_server.py \
&& grep -Fq 'agent._hermes_explicit_model_pick' \ && grep -Fq 'agent._hermes_explicit_model_pick' \
/opt/hermes/gateway/platforms/api_server.py \ /opt/hermes/gateway/platforms/api_server.py \
&& grep -Fq 'managed_claude_code_subscription' \
/opt/hermes/hermes_cli/web_server.py \
&& grep -Fq 'Claude Code subscription (Switchyard)' \
/opt/hermes/hermes_cli/web_server.py \
&& grep -Fq '"pre_turn_route"' /opt/hermes/hermes_cli/plugins.py \ && grep -Fq '"pre_turn_route"' /opt/hermes/hermes_cli/plugins.py \
&& grep -Fq '"pre_internal_route"' /opt/hermes/hermes_cli/plugins.py \ && grep -Fq '"pre_internal_route"' /opt/hermes/hermes_cli/plugins.py \
&& grep -Fq '"pre_subagent_route"' /opt/hermes/hermes_cli/plugins.py \ && grep -Fq '"pre_subagent_route"' /opt/hermes/hermes_cli/plugins.py \

View File

@ -149,6 +149,10 @@ def test_gateway_image_honors_ui_model_and_caps_reasoning():
assert "pre_internal_route hook failed" in dockerfile assert "pre_internal_route hook failed" in dockerfile
assert '"pre_subagent_route"' in dockerfile assert '"pre_subagent_route"' in dockerfile
assert "pre_subagent_route hook failed" in dockerfile assert "pre_subagent_route hook failed" in dockerfile
assert 'var != "CLAUDE_CODE_OAUTH_TOKEN"' in dockerfile
assert '"source": "managed_claude_code_subscription"' in dockerfile
assert '"name": "Claude Code subscription (Switchyard)"' in dockerfile
assert "Anthropic API / direct OAuth (not used by Switchyard)" in dockerfile
def test_chat_oauth_allows_stale_service_worker_retirement(): def test_chat_oauth_allows_stale_service_worker_retirement():