mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix: chatd refactor (#26270)
Implements the chatd stabilization RFC. Combines: - https://github.com/coder/coder/pull/25908 - https://github.com/coder/coder/pull/25923 - https://github.com/coder/coder/pull/26109 - https://github.com/coder/coder/pull/26110 - https://github.com/coder/coder/pull/26111 - https://github.com/coder/coder/pull/26112
This commit is contained in:
+24
-2
@@ -93,6 +93,7 @@ const (
|
||||
ChatStatusCompleted ChatStatus = "completed"
|
||||
ChatStatusError ChatStatus = "error"
|
||||
ChatStatusRequiresAction ChatStatus = "requires_action"
|
||||
ChatStatusInterrupting ChatStatus = "interrupting"
|
||||
)
|
||||
|
||||
// ChatClientType indicates whether a chat was created from the
|
||||
@@ -1502,6 +1503,8 @@ const (
|
||||
ChatStreamEventTypeQueueUpdate ChatStreamEventType = "queue_update"
|
||||
ChatStreamEventTypeRetry ChatStreamEventType = "retry"
|
||||
ChatStreamEventTypeActionRequired ChatStreamEventType = "action_required"
|
||||
ChatStreamEventTypePreviewReset ChatStreamEventType = "preview_reset"
|
||||
ChatStreamEventTypeHistoryReset ChatStreamEventType = "history_reset"
|
||||
)
|
||||
|
||||
// ChatQueuedMessage represents a queued message waiting to be processed.
|
||||
@@ -1515,8 +1518,11 @@ type ChatQueuedMessage struct {
|
||||
|
||||
// ChatStreamMessagePart is a streamed message part update.
|
||||
type ChatStreamMessagePart struct {
|
||||
Role ChatMessageRole `json:"role,omitempty"`
|
||||
Part ChatMessagePart `json:"part"`
|
||||
Role ChatMessageRole `json:"role,omitempty"`
|
||||
Part ChatMessagePart `json:"part"`
|
||||
HistoryVersion int64 `json:"history_version,omitempty"`
|
||||
GenerationAttempt int64 `json:"generation_attempt,omitempty"`
|
||||
Seq int64 `json:"seq,omitempty"`
|
||||
}
|
||||
|
||||
// ChatStreamStatus represents an updated chat status.
|
||||
@@ -3250,6 +3256,22 @@ func (c *ExperimentalClient) InterruptChat(ctx context.Context, chatID uuid.UUID
|
||||
return chat, json.NewDecoder(res.Body).Decode(&chat)
|
||||
}
|
||||
|
||||
// ReconcileInvalidChatState recovers a chat stuck in an invalid
|
||||
// execution state, moving it into an error state from which the caller
|
||||
// can send a new message or edit history to continue.
|
||||
func (c *ExperimentalClient) ReconcileInvalidChatState(ctx context.Context, chatID uuid.UUID) (Chat, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/experimental/chats/%s/reconcile-invalid", chatID), nil)
|
||||
if err != nil {
|
||||
return Chat{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return Chat{}, ReadBodyAsError(res)
|
||||
}
|
||||
var chat Chat
|
||||
return chat, json.NewDecoder(res.Body).Decode(&chat)
|
||||
}
|
||||
|
||||
// RegenerateChatTitle requests the server to regenerate the chat's
|
||||
// title using richer conversation context.
|
||||
func (c *ExperimentalClient) RegenerateChatTitle(ctx context.Context, chatID uuid.UUID) (Chat, error) {
|
||||
|
||||
@@ -172,6 +172,42 @@ func TestChatErrorKind_JSONRoundTrip(t *testing.T) {
|
||||
require.Equal(t, codersdk.ChatErrorKindUsageLimit, decodedRetry.Kind)
|
||||
}
|
||||
|
||||
func TestChatStreamEvent_JSONRoundTripIncludesResetTypesAndPartMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
chatID := uuid.New()
|
||||
events := []codersdk.ChatStreamEvent{
|
||||
{Type: codersdk.ChatStreamEventTypePreviewReset, ChatID: chatID},
|
||||
{Type: codersdk.ChatStreamEventTypeHistoryReset, ChatID: chatID},
|
||||
{
|
||||
Type: codersdk.ChatStreamEventTypeMessagePart,
|
||||
ChatID: chatID,
|
||||
MessagePart: &codersdk.ChatStreamMessagePart{
|
||||
Role: codersdk.ChatMessageRoleAssistant,
|
||||
Part: codersdk.ChatMessageText("partial"),
|
||||
HistoryVersion: 12,
|
||||
GenerationAttempt: 3,
|
||||
Seq: 4,
|
||||
},
|
||||
},
|
||||
}
|
||||
data, err := json.Marshal(events)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, string(data), `"type":"preview_reset"`)
|
||||
require.Contains(t, string(data), `"type":"history_reset"`)
|
||||
require.Contains(t, string(data), `"history_version":12`)
|
||||
require.Contains(t, string(data), `"generation_attempt":3`)
|
||||
require.Contains(t, string(data), `"seq":4`)
|
||||
|
||||
var decoded []codersdk.ChatStreamEvent
|
||||
require.NoError(t, json.Unmarshal(data, &decoded))
|
||||
require.Equal(t, codersdk.ChatStreamEventTypePreviewReset, decoded[0].Type)
|
||||
require.Equal(t, codersdk.ChatStreamEventTypeHistoryReset, decoded[1].Type)
|
||||
require.Equal(t, int64(12), decoded[2].MessagePart.HistoryVersion)
|
||||
require.Equal(t, int64(3), decoded[2].MessagePart.GenerationAttempt)
|
||||
require.Equal(t, int64(4), decoded[2].MessagePart.Seq)
|
||||
}
|
||||
|
||||
func TestChatMessagePart_StripInternal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user