Compare commits

...

1 Commits

Author SHA1 Message Date
Teknium
1e36185b70 fix(auth): kimi-coding pool base_url seeding + PKCE endpoint fallback
1. credential_pool._seed_from_env() now calls _resolve_kimi_base_url()
   for kimi-coding provider, matching the runtime resolver logic.
   Previously, sk-kimi- prefixed keys were seeded with the default
   moonshot.ai URL, causing 401 on first request. Fixes #5561.

2. Hermes-native PKCE OAuth login (run_hermes_oauth_login_pure) now
   tries platform.claude.com first with console.anthropic.com fallback,
   consistent with refresh_anthropic_oauth_pure(). The old _OAUTH_TOKEN_URL
   constant hardcoded console.anthropic.com only.
2026-04-07 00:00:34 -07:00
2 changed files with 31 additions and 13 deletions

View File

@@ -591,7 +591,10 @@ def run_oauth_setup_token() -> Optional[str]:
# Stores credentials in ~/.hermes/.anthropic_oauth.json (our own file).
_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
_OAUTH_TOKEN_URL = "https://console.anthropic.com/v1/oauth/token"
_OAUTH_TOKEN_URLS = [
"https://platform.claude.com/v1/oauth/token",
"https://console.anthropic.com/v1/oauth/token",
]
_OAUTH_REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback"
_OAUTH_SCOPES = "org:create_api_key user:profile user:inference"
_HERMES_OAUTH_FILE = get_hermes_home() / ".anthropic_oauth.json"
@@ -676,18 +679,29 @@ def run_hermes_oauth_login_pure() -> Optional[Dict[str, Any]]:
"code_verifier": verifier,
}).encode()
req = urllib.request.Request(
_OAUTH_TOKEN_URL,
data=exchange_data,
headers={
"Content-Type": "application/json",
"User-Agent": f"claude-cli/{_get_claude_code_version()} (external, cli)",
},
method="POST",
)
result = None
last_error = None
for endpoint in _OAUTH_TOKEN_URLS:
req = urllib.request.Request(
endpoint,
data=exchange_data,
headers={
"Content-Type": "application/json",
"User-Agent": f"claude-cli/{_get_claude_code_version()} (external, cli)",
},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=15) as resp:
result = json.loads(resp.read().decode())
break
except Exception as exc:
logger.debug("Token exchange failed at %s: %s", endpoint, exc)
last_error = exc
continue
with urllib.request.urlopen(req, timeout=15) as resp:
result = json.loads(resp.read().decode())
if result is None:
raise last_error or ValueError("Token exchange failed on all endpoints")
except Exception as e:
print(f"Token exchange failed: {e}")
return None

View File

@@ -27,6 +27,7 @@ from hermes_cli.auth import (
_is_expiring,
_load_auth_store,
_load_provider_state,
_resolve_kimi_base_url,
read_credential_pool,
write_credential_pool,
)
@@ -1085,7 +1086,10 @@ def _seed_from_env(provider: str, entries: List[PooledCredential]) -> Tuple[bool
source = f"env:{env_var}"
active_sources.add(source)
auth_type = AUTH_TYPE_OAUTH if provider == "anthropic" and not token.startswith("sk-ant-api") else AUTH_TYPE_API_KEY
base_url = env_url or pconfig.inference_base_url
if provider == "kimi-coding":
base_url = _resolve_kimi_base_url(token, pconfig.inference_base_url, env_url)
else:
base_url = env_url or pconfig.inference_base_url
changed |= _upsert_entry(
entries,
provider,