mirror of
https://github.com/coder/coder.git
synced 2026-06-07 15:08:20 +00:00
21c2acbad5
Follow-up to #23282. The retry and terminal error callouts had a few UX oddities: - Auto-retrying states reused backend error text that said "Please try again" even while the UI was already retrying on behalf of the user. - Terminal error states also said "Please try again" with no action the user could take. - `startup_timeout` had no specific title or retry copy — it fell through to the generic "Retrying request" heading. - The kind pill showed raw enum values like `startup_timeout` and `rate_limit`. - Terminal error metadata showed a "Retryable" / "Not retryable" label that does not help users. - A separate "Provider anthropic" metadata row duplicated information already present in the message body. - The `usage-limit` error kind used a hyphen while every backend kind uses underscores. Changes: **Backend (`chaterror/message.go`)** - Split message generation into `terminalMessage()` and `retryMessage()`, replacing the old `userFacingMessage()`. - Terminal messages include HTTP status codes and actionable guidance (e.g. "Check the API key, permissions, and billing settings."). - Retry messages are clean factual statements without status codes or remediation, suitable for the retry countdown UI (e.g. "Anthropic is temporarily overloaded."). - Removed "Please try again" / "Please try again later" from all paths. - `StreamRetryPayload` calls `retryMessage()` instead of forwarding `classified.Message`. **Frontend** - Removed the parallel frontend message-generation system: `getRetryMessage()`, `getProviderDisplayName()`, `getRetryProviderSubject()`, and the `PROVIDER_DISPLAY_NAMES` map are all deleted from `chatStatusHelpers.ts`. - `liveStatusModel.ts` passes `retryState.error` through directly — the backend owns the copy. - Added specific title and retry copy for `startup_timeout`, and extended the title mapping to cover `auth` and `config`. - Kind pills now show humanized labels ("Startup timeout", "Rate limit", etc.) instead of raw enum strings. - Removed the redundant "Provider anthropic" metadata row. - Removed the terminal "Retryable" / "Not retryable" badge. - Normalized `"usage-limit"` → `"usage_limit"` and added it to `ChatProviderFailureKind` so all error kinds follow the same underscore convention and live in one enum. Refs #23282.
61 lines
1.7 KiB
Go
61 lines
1.7 KiB
Go
package chaterror_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/coder/coder/v2/coderd/x/chatd/chaterror"
|
|
"github.com/coder/coder/v2/codersdk"
|
|
)
|
|
|
|
func TestStreamErrorPayloadUsesNormalizedClassification(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
classified := chaterror.Classify(
|
|
xerrors.New("azure openai received status 429 from upstream"),
|
|
)
|
|
payload := chaterror.StreamErrorPayload(classified)
|
|
|
|
require.Equal(t, &codersdk.ChatStreamError{
|
|
Message: "Azure OpenAI is rate limiting requests (HTTP 429).",
|
|
Kind: chaterror.KindRateLimit,
|
|
Provider: "azure",
|
|
Retryable: true,
|
|
StatusCode: 429,
|
|
}, payload)
|
|
}
|
|
|
|
func TestStreamErrorPayloadNilForEmptyClassification(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
require.Nil(t, chaterror.StreamErrorPayload(chaterror.ClassifiedError{}))
|
|
}
|
|
|
|
func TestStreamRetryPayloadUsesNormalizedClassification(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
delay := 3 * time.Second
|
|
startedAt := time.Now()
|
|
payload := chaterror.StreamRetryPayload(2, delay, chaterror.ClassifiedError{
|
|
Message: "OpenAI returned an unexpected error (HTTP 503).",
|
|
Kind: chaterror.KindGeneric,
|
|
Provider: "openai",
|
|
Retryable: true,
|
|
StatusCode: 503,
|
|
})
|
|
|
|
require.NotNil(t, payload)
|
|
require.Equal(t, 2, payload.Attempt)
|
|
require.Equal(t, delay.Milliseconds(), payload.DelayMs)
|
|
// Retry messages omit the HTTP status code; the status code is
|
|
// surfaced separately in the payload's StatusCode field.
|
|
require.Equal(t, "OpenAI returned an unexpected error.", payload.Error)
|
|
require.Equal(t, chaterror.KindGeneric, payload.Kind)
|
|
require.Equal(t, "openai", payload.Provider)
|
|
require.Equal(t, 503, payload.StatusCode)
|
|
require.WithinDuration(t, startedAt.Add(delay), payload.RetryingAt, time.Second)
|
|
}
|