language_models_cloud: Classify LLM token failures as provider rejections (#64754)
`CloudLlmTokenProvider` returned `anyhow::Result`, and
`authenticated_llm_request` reported every failure, including failing to
mint an LLM token, as `LanguageModelCompletionError::HttpSend`. An
expired session (401) or a missing subscription (402) during token
minting therefore looked like a connectivity problem: the agent panel
showed a stream error, and retry logic treated it as transient.
Downstream consumers (Delta) had to dig typed errors back out of the
`anyhow` chain to recover the real cause.
This PR:
- Changes `CloudLlmTokenProvider::cached_token`/`refresh_token` to
return `Result<String, ClientApiError>`, and
`Client::{cached,refresh,clear_and_refresh}_llm_token` to match.
- Adds `LlmRequestError`, returned by `authenticated_llm_request`, which
separates token acquisition failures from building or sending the
request.
- Adds `LlmRequestError::into_completion_error`, which maps:
- `Unauthorized`/`NotSignedIn` to a Zed `Authentication` rejection (not
retried),
- a token-endpoint 402 to the existing `PaymentRequired` rejection,
- other token-endpoint statuses by HTTP status (for example 403 to
`Permission`, 5xx to retryable `InternalServer`),
- connection failures and send failures to `HttpSend`, as before.
In Zed, a token failure caused by an expired session now shows the agent
panel's authentication error instead of a stream error. Messages stay
neutral about whose credentials were rejected so callers can choose
wording from the category.
Release Notes:
- Improved the agent panel error shown when a Zed sign-in has expired.
dd510f99e0Conrad Irwin committed on 9/28/2026, 7:11:12 PM· committed by GitHubparent72d28c3