fix(credential-pool): hydrate on-disk env rows on the openrouter branch too
The openrouter branch of _seed_from_env returns before the generic loop, so a persisted `env:OPENROUTER_API_KEY_2` row stayed empty exactly like the registry-provider case #103067 fixed. Fold the "declared vars + on-disk env rows" union into one helper both branches use.
This commit is contained in:
@@ -2566,6 +2566,24 @@ _ENV_BASE_URL_RESOLVERS = {
|
||||
}
|
||||
|
||||
|
||||
def _with_on_disk_env_sources(env_vars: List[str], entries: List[PooledCredential]) -> List[str]:
|
||||
"""*env_vars* plus the ``env:VAR`` names already persisted in the pool.
|
||||
|
||||
Env-backed rows are written to auth.json without their secret and
|
||||
re-hydrated on every load; a row whose VAR the registry does not
|
||||
declare (a second key the user pointed at ``env:PROVIDER_API_KEY_2``)
|
||||
would otherwise stay empty forever and be silently dropped from
|
||||
rotation by ``_available_entries``.
|
||||
"""
|
||||
names = list(env_vars)
|
||||
for entry in entries:
|
||||
if entry.source.startswith("env:"):
|
||||
env_name = entry.source.split(":", 1)[1].strip()
|
||||
if env_name and env_name not in names:
|
||||
names.append(env_name)
|
||||
return names
|
||||
|
||||
|
||||
def _seed_from_env(provider: str, entries: List[PooledCredential]) -> Tuple[bool, Set[str]]:
|
||||
seed = _Seeder(provider, entries)
|
||||
# Copilot's singleton branch exchanges the raw ghu_ OAuth token for the
|
||||
@@ -2576,12 +2594,13 @@ def _seed_from_env(provider: str, entries: List[PooledCredential]) -> Tuple[bool
|
||||
return seed.result
|
||||
|
||||
if provider == "openrouter":
|
||||
token = get_env_prefer_dotenv("OPENROUTER_API_KEY")
|
||||
if token and seed.upsert(
|
||||
"env:OPENROUTER_API_KEY",
|
||||
_env_payload(env_var="OPENROUTER_API_KEY", token=token, base_url=OPENROUTER_BASE_URL),
|
||||
):
|
||||
_warn_env_ingestion_once(provider, "OPENROUTER_API_KEY")
|
||||
for env_var in _with_on_disk_env_sources(["OPENROUTER_API_KEY"], entries):
|
||||
token = get_env_prefer_dotenv(env_var)
|
||||
if token and seed.upsert(
|
||||
f"env:{env_var}",
|
||||
_env_payload(env_var=env_var, token=token, base_url=OPENROUTER_BASE_URL),
|
||||
):
|
||||
_warn_env_ingestion_once(provider, env_var)
|
||||
return seed.result
|
||||
|
||||
pconfig = PROVIDER_REGISTRY.get(provider)
|
||||
@@ -2595,17 +2614,7 @@ def _seed_from_env(provider: str, entries: List[PooledCredential]) -> Tuple[bool
|
||||
env_vars = list(pconfig.api_key_env_vars)
|
||||
if provider == "anthropic":
|
||||
env_vars = ["ANTHROPIC_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN", "ANTHROPIC_API_KEY"]
|
||||
|
||||
# Also seed any env-source pool entries already on disk that aren't in
|
||||
# the registry's tuple. A user can put `source: env:OPENCODE_GO_API_KEY2`
|
||||
# in auth.json expecting it to be picked up from the environment; the
|
||||
# registry only declares the primary env var, so this loop fills the
|
||||
# gap and keeps multi-key rotation working without per-provider code.
|
||||
for entry in entries:
|
||||
if entry.source.startswith("env:"):
|
||||
env_name = entry.source.split(":", 1)[1]
|
||||
if env_name and env_name not in env_vars:
|
||||
env_vars.append(env_name)
|
||||
env_vars = _with_on_disk_env_sources(env_vars, entries)
|
||||
|
||||
resolve_base_url = _ENV_BASE_URL_RESOLVERS.get(provider)
|
||||
for env_var in env_vars:
|
||||
|
||||
Reference in New Issue
Block a user