refactor: move chat error kinds into codersdk (#24955)

Moves the chat error kind taxonomy from `coderd/x/chatd/chaterror` into
`codersdk.ChatErrorKind` and types `ChatError.Kind` /
`ChatStreamRetry.Kind` so generated TypeScript exposes an SDK-owned
union, including `usage_limit`. Backend chat classification now
references the SDK constants directly while preserving the existing JSON
string values.

Keeps chat usage-limit admission failures on their existing 409 response
shape. The frontend maps structured usage-limit responses to the
SDK-owned `usage_limit` kind, uses generated `TypesGen.ChatErrorKind`
directly, and removes the local string union and alias.
This commit is contained in:
Ethan
2026-05-06 11:57:48 +10:00
committed by GitHub
parent dc14ab6b97
commit 46a60e6d5d
29 changed files with 305 additions and 233 deletions
+3 -4
View File
@@ -28,7 +28,6 @@ import (
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
"github.com/coder/coder/v2/coderd/x/chatd/chaterror"
"github.com/coder/coder/v2/coderd/x/chatd/chatprompt"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisionersdk/proto"
@@ -1619,16 +1618,16 @@ func decodeChatLastError(raw pqtype.NullRawMessage) *codersdk.ChatError {
if err := json.Unmarshal(raw.RawMessage, &payload); err != nil {
return &codersdk.ChatError{
Message: fallbackChatLastErrorMessage,
Kind: chaterror.KindGeneric,
Kind: codersdk.ChatErrorKindGeneric,
}
}
payload.Message = strings.TrimSpace(payload.Message)
payload.Detail = strings.TrimSpace(payload.Detail)
payload.Kind = strings.TrimSpace(payload.Kind)
payload.Kind = codersdk.ChatErrorKind(strings.TrimSpace(string(payload.Kind)))
payload.Provider = strings.TrimSpace(payload.Provider)
if payload.Kind == "" {
payload.Kind = chaterror.KindGeneric
payload.Kind = codersdk.ChatErrorKindGeneric
}
if payload.Message == "" {
payload.Message = fallbackChatLastErrorMessage
+14 -6
View File
@@ -19,7 +19,6 @@ import (
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/x/chatd/chaterror"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/provisionersdk/proto"
)
@@ -920,7 +919,7 @@ func TestChat_AllFieldsPopulated(t *testing.T) {
lastErrorPayload := codersdk.ChatError{
Message: "boom",
Detail: "provider detail",
Kind: chaterror.KindGeneric,
Kind: codersdk.ChatErrorKindGeneric,
Provider: "openai",
Retryable: true,
StatusCode: 503,
@@ -1082,7 +1081,7 @@ func TestChat_LastErrorFallback(t *testing.T) {
raw: json.RawMessage(`{`),
expectPayload: &codersdk.ChatError{
Message: fallbackMessage,
Kind: chaterror.KindGeneric,
Kind: codersdk.ChatErrorKindGeneric,
Retryable: false,
},
},
@@ -1091,7 +1090,7 @@ func TestChat_LastErrorFallback(t *testing.T) {
raw: json.RawMessage(`{"kind":"timeout","provider":"openai","status_code":504}`),
expectPayload: &codersdk.ChatError{
Message: fallbackMessage,
Kind: "timeout",
Kind: codersdk.ChatErrorKindTimeout,
Provider: "openai",
Retryable: false,
StatusCode: 504,
@@ -1102,7 +1101,7 @@ func TestChat_LastErrorFallback(t *testing.T) {
raw: json.RawMessage(`{"message":" ","provider":"openai"}`),
expectPayload: &codersdk.ChatError{
Message: fallbackMessage,
Kind: chaterror.KindGeneric,
Kind: codersdk.ChatErrorKindGeneric,
Provider: "openai",
Retryable: false,
},
@@ -1112,12 +1111,21 @@ func TestChat_LastErrorFallback(t *testing.T) {
raw: json.RawMessage(`{"message":"OpenAI returned an unexpected error.","provider":"openai","status_code":502}`),
expectPayload: &codersdk.ChatError{
Message: "OpenAI returned an unexpected error.",
Kind: chaterror.KindGeneric,
Kind: codersdk.ChatErrorKindGeneric,
Provider: "openai",
Retryable: false,
StatusCode: 502,
},
},
{
name: "UsageLimitKindRoundTrips",
raw: json.RawMessage(`{"message":"Usage limit reached.","kind":"usage_limit"}`),
expectPayload: &codersdk.ChatError{
Message: "Usage limit reached.",
Kind: codersdk.ChatErrorKindUsageLimit,
Retryable: false,
},
},
}
for _, tc := range tests {