fix: separate Anthropic OAuth tokens from API keys

Persist OAuth/setup tokens in ANTHROPIC_TOKEN instead of ANTHROPIC_API_KEY.
Reserve ANTHROPIC_API_KEY for regular Console API keys.

Changes:
- anthropic_adapter: reorder resolve_anthropic_token() priority —
  ANTHROPIC_TOKEN first, ANTHROPIC_API_KEY as legacy fallback
- config: add save_anthropic_oauth_token() / save_anthropic_api_key() helpers
  that clear the opposing slot to prevent priority conflicts
- config: show_config() prefers ANTHROPIC_TOKEN for display
- setup: OAuth login and pasted setup-tokens write to ANTHROPIC_TOKEN
- setup: API key entry writes to ANTHROPIC_API_KEY and clears ANTHROPIC_TOKEN
- main: same fixes in _run_anthropic_oauth_flow() and _model_flow_anthropic()
- main: _has_any_provider_configured() checks ANTHROPIC_TOKEN
- doctor: use _is_oauth_token() for correct auth method validation
- runtime_provider: updated error message
- run_agent: simplified client init to use resolve_anthropic_token()
- run_agent: updated 401 troubleshooting messages
- status: prefer ANTHROPIC_TOKEN in status display
- tests: updated priority test, added persistence helper tests

Cherry-picked from PR #1141 by kshitijk4poor, rebased onto current main
with unrelated changes (web_policy config, blocklist CLI) removed.

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
This commit is contained in:
kshitijk4poor 2026-03-13 02:09:52 -07:00 committed by teknium1
parent f562d97f13
commit bb3f5ed32a
10 changed files with 114 additions and 43 deletions

View file

@ -1074,6 +1074,7 @@ def setup_model_provider(config: dict):
print()
print_header("Anthropic Authentication")
from hermes_cli.auth import PROVIDER_REGISTRY
from hermes_cli.config import save_anthropic_api_key, save_anthropic_oauth_token
pconfig = PROVIDER_REGISTRY["anthropic"]
# Check ALL credential sources
@ -1086,8 +1087,8 @@ def setup_model_provider(config: dict):
cc_valid = bool(cc_creds and is_claude_code_token_valid(cc_creds))
existing_key = (
get_env_value("ANTHROPIC_API_KEY")
or get_env_value("ANTHROPIC_TOKEN")
get_env_value("ANTHROPIC_TOKEN")
or get_env_value("ANTHROPIC_API_KEY")
or _os.getenv("CLAUDE_CODE_OAUTH_TOKEN", "")
)
@ -1127,14 +1128,14 @@ def setup_model_provider(config: dict):
print()
token = run_oauth_setup_token()
if token:
save_env_value("ANTHROPIC_API_KEY", token)
save_anthropic_oauth_token(token, save_fn=save_env_value)
print_success("OAuth credentials saved")
else:
# Subprocess completed but no token auto-detected
print()
token = prompt("Paste setup-token here (if displayed above)", password=True)
if token:
save_env_value("ANTHROPIC_API_KEY", token)
save_anthropic_oauth_token(token, save_fn=save_env_value)
print_success("Setup-token saved")
else:
print_warning("Skipped — agent won't work without credentials")
@ -1148,7 +1149,7 @@ def setup_model_provider(config: dict):
print()
token = prompt("Setup-token (sk-ant-oat-...)", password=True)
if token:
save_env_value("ANTHROPIC_API_KEY", token)
save_anthropic_oauth_token(token, save_fn=save_env_value)
print_success("Setup-token saved")
else:
print_warning("Skipped — install Claude Code and re-run setup")
@ -1158,7 +1159,7 @@ def setup_model_provider(config: dict):
print()
api_key = prompt("API key (sk-ant-...)", password=True)
if api_key:
save_env_value("ANTHROPIC_API_KEY", api_key)
save_anthropic_api_key(api_key, save_fn=save_env_value)
print_success("API key saved")
else:
print_warning("Skipped — agent won't work without credentials")