fix(desktop): pass provider_primary through /api/env so a card keeps its own key

_row() forwarded provider, provider_label and provider_profiles from the
catalog metadata but dropped provider_primary, so a provider card's own
index-0 credential (ALIBABA_CODING_PLAN_CN_API_KEY) reached the Keys tab
with provider_primary unset. buildProviderKeyGroups then fell through to
the first non-advanced key var — which, for the (Coding Plan, China) and
(Token Plan, China) cards, is a shared fallback alias (DASHSCOPE_API_KEY /
ALIBABA_TOKEN_PLAN_API_KEY) contributed by peer profiles with primary:
false. The card's Paste key wrote a foreign tier's credential and the
CN-specific var was rendered nowhere when unset.

Regression test: test_get_api_env_passes_provider_primary_through pins
the CN card's own key as provider_primary=True and the shared DASHSCOPE
alias as primary=False from that provider's profile.
This commit is contained in:
Hermes Agent
2026-09-25 18:54:12 -05:00
committed by brooklyn!
parent 7ca2f5665f
commit 2497c3c539
2 changed files with 38 additions and 0 deletions

View File

@@ -295,6 +295,11 @@ def _get_env_vars_sync(profile: Optional[str] = None):
# Preserve those identities so Desktop can render distinct cards
# that edit the same underlying env var.
"provider_profiles": cat_meta.get("provider_profiles", []),
# The provider's own index-0 credential flag. Desktop picks a card's
# main "Paste key" field from this FIRST, so a shared alias that a
# peer profile contributes (DASHSCOPE_API_KEY for the CN Coding /
# Token Plan cards) can never re-point the card's primary field.
"provider_primary": bool(cat_meta.get("provider_primary", False)),
# True for a .env key in no catalog at all — an arbitrary/custom var
# the user added directly, listed so the Keys page can manage it.
"custom": custom,

View File

@@ -309,3 +309,36 @@ def test_scrub_never_touches_providers_base_url_alias(hermes_home):
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
# GET /api/env — provider_primary pass-through for the Desktop Keys tab
# ---------------------------------------------------------------------------
# The Desktop groups a provider card's rows by provider_label and picks the
# card's main "Paste key" field from `provider_primary` first. That flag is
# computed per catalog entry in _catalog_provider_env_metadata (index == 0 of
# the provider's own api_key_env_vars) but _row used to drop it, so a card's
# own first credential arrived with provider_primary=None and the grouping
# fell back to the first non-advanced key var — which, for a profile-shared
# credential contributed by peer providers (DASHSCOPE_API_KEY is index >= 1
# of alibaba-coding-plan-cn), could be a FOREIGN tier's key.
def test_get_api_env_passes_provider_primary_through(hermes_home):
"""Every provider card's own index-0 credential must stay its main field."""
resp = client.get("/api/env", headers=HEADERS)
assert resp.status_code == 200, resp.text
env = resp.json()
# The CN Coding Plan card: its own key is its primary; the shared
# DASHSCOPE_API_KEY alias joins the card marked primary=False.
assert env["ALIBABA_CODING_PLAN_CN_API_KEY"]["provider_primary"] is True
dashscope = env["DASHSCOPE_API_KEY"]["provider_profiles"]
cn_profile = next(
p for p in dashscope if p["provider"] == "alibaba-coding-plan-cn"
)
assert cn_profile["primary"] is False, (
"DASHSCOPE_API_KEY is a fallback alias for alibaba-coding-plan-cn; "
"marking it primary would re-point the card's main field away from "
"ALIBABA_CODING_PLAN_CN_API_KEY"
)