mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix!: persist structured chat errors (#24919)
**Breaking change for changelog:**
> `codersdk.Chat.last_error` now returns a structured `ChatError` object
(`{message, kind, provider, retryable, status_code, detail}`) instead of
a plain string. The chats API is experimental
(`/api/experimental/chats`), so this ships without a deprecation cycle;
consumers reading `chat.last_error` as a string must update to read
`chat.last_error.message`. SDK/generated TypeScript terminal error
payloads now use the single `ChatError` type; the live stream error
payload type is renamed from `ChatStreamError` to `ChatError`.
Persisted chat errors now carry the same provider-specific detail (kind,
provider, retryable, HTTP status, optional detail) as the live stream,
so refreshing a failed chat rehydrates with the full structured error
instead of a one-line headline.
Existing rows are migrated in place: legacy text errors are wrapped into
`{message, kind: "generic"}` so already-errored chats still render, and
rows with `last_error IS NULL` stay NULL. Internally, persisted fallback
decoding now reuses the existing `chaterror.KindGeneric` constant, with
no JSON value change.
Closes CODAGT-239
This commit is contained in:
+1
-1
@@ -1287,7 +1287,7 @@ func (m chatViewModel) handleStreamEvent(event codersdk.ChatStreamEvent) (chatVi
|
||||
chatID: m.activeChatID,
|
||||
event: codersdk.ChatStreamEvent{
|
||||
Type: codersdk.ChatStreamEventTypeError,
|
||||
Error: &codersdk.ChatStreamError{
|
||||
Error: &codersdk.ChatError{
|
||||
Message: fmt.Sprintf(
|
||||
"failed to parse ask_user_question: %v",
|
||||
err,
|
||||
|
||||
+4
-3
@@ -78,7 +78,7 @@ func (m chatListModel) filteredChats() []codersdk.Chat {
|
||||
filtered = append(filtered, chat)
|
||||
continue
|
||||
}
|
||||
if chat.LastError != nil && strings.Contains(strings.ToLower(*chat.LastError), query) {
|
||||
if chat.LastError != nil && strings.Contains(strings.ToLower(chat.LastError.Message), query) {
|
||||
filtered = append(filtered, chat)
|
||||
}
|
||||
}
|
||||
@@ -445,13 +445,14 @@ func (m chatListModel) View() string {
|
||||
rowText := fmt.Sprintf("%s%s %s %s%s", rowPrefix, rowStyle.Render(title), status, m.styles.dimmedText.Render(timeAgo(row.chat.UpdatedAt)), extra)
|
||||
lines = append(lines, rowText)
|
||||
|
||||
if row.chat.Status == codersdk.ChatStatusError && row.chat.LastError != nil {
|
||||
if row.chat.Status == codersdk.ChatStatusError && row.chat.LastError != nil && row.chat.LastError.Message != "" {
|
||||
lastError := row.chat.LastError.Message
|
||||
errWidth := max(m.width-4, 20)
|
||||
errPrefix := " "
|
||||
if row.depth > 0 {
|
||||
errPrefix += strings.Repeat(" ", row.depth)
|
||||
}
|
||||
lines = append(lines, errPrefix+m.styles.dimmedText.Render(m.styles.truncate(sanitizeTerminalRenderableText(*row.chat.LastError), errWidth)))
|
||||
lines = append(lines, errPrefix+m.styles.dimmedText.Render(m.styles.truncate(sanitizeTerminalRenderableText(lastError), errWidth)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ func TestConsumeChatStreamText(t *testing.T) {
|
||||
{Type: codersdk.ChatStreamEventTypeMessage, Message: &codersdk.ChatMessage{ID: 1, ChatID: uuid.New(), Role: codersdk.ChatMessageRoleAssistant, Content: []codersdk.ChatMessagePart{{Type: codersdk.ChatMessagePartTypeText, Text: "Hello world"}}}},
|
||||
{Type: codersdk.ChatStreamEventTypeStatus, Status: &codersdk.ChatStreamStatus{Status: codersdk.ChatStatusRunning}},
|
||||
{Type: codersdk.ChatStreamEventTypeRetry, Retry: &codersdk.ChatStreamRetry{Attempt: 2, Error: "rate limited"}},
|
||||
{Type: codersdk.ChatStreamEventTypeError, Error: &codersdk.ChatStreamError{Message: "boom"}},
|
||||
{Type: codersdk.ChatStreamEventTypeError, Error: &codersdk.ChatError{Message: "boom"}},
|
||||
} {
|
||||
events <- event
|
||||
}
|
||||
|
||||
+1
-1
@@ -1070,7 +1070,7 @@ func TestAgents(t *testing.T) {
|
||||
t.Parallel()
|
||||
updated, cmd := applyStream(newTestChatViewModel(nil), codersdk.ChatStreamEvent{
|
||||
Type: codersdk.ChatStreamEventTypeError,
|
||||
Error: &codersdk.ChatStreamError{Message: "stream blew up"},
|
||||
Error: &codersdk.ChatError{Message: "stream blew up"},
|
||||
})
|
||||
require.Nil(t, cmd)
|
||||
require.Equal(t, "stream error: stream blew up", updated.err.Error())
|
||||
|
||||
Reference in New Issue
Block a user