diff --git a/coderd/chatd/chatd.go b/coderd/chatd/chatd.go index 55f7a2fdb6..bc53dd4fdf 100644 --- a/coderd/chatd/chatd.go +++ b/coderd/chatd/chatd.go @@ -1430,6 +1430,24 @@ func (p *Server) publishChatPubsubEvent(chat database.Chat, kind coderdpubsub.Ch } } +// PublishDiffStatusChange broadcasts a diff_status_change event for +// the given chat so that watching clients know to re-fetch the diff +// status. This is called from the HTTP layer after the diff status +// is updated in the database. +func (p *Server) PublishDiffStatusChange(ctx context.Context, chatID uuid.UUID) error { + if p.pubsub == nil { + return nil + } + + chat, err := p.db.GetChatByID(ctx, chatID) + if err != nil { + return xerrors.Errorf("get chat: %w", err) + } + + p.publishChatPubsubEvent(chat, coderdpubsub.ChatEventKindDiffStatusChange) + return nil +} + func (p *Server) publishError(chatID uuid.UUID, message string) { message = strings.TrimSpace(message) if message == "" { diff --git a/coderd/chats.go b/coderd/chats.go index 908acc30fb..c09e5e8d04 100644 --- a/coderd/chats.go +++ b/coderd/chats.go @@ -1068,7 +1068,9 @@ func (api *API) storeChatGitRef(ctx context.Context, workspaceID, workspaceOwner slog.F("workspace_id", workspaceID), slog.Error(err), ) + continue } + api.publishChatDiffStatusEvent(ctx, chat.ID) } } @@ -1109,6 +1111,7 @@ func (api *API) refreshWorkspaceChatDiffStatuses(ctx context.Context, workspaceI } api.publishChatStatusEvent(ctx, chat.ID) + api.publishChatDiffStatusEvent(ctx, chat.ID) } return allHavePR @@ -1138,6 +1141,19 @@ func (api *API) publishChatStatusEvent(ctx context.Context, chatID uuid.UUID) { } } +func (api *API) publishChatDiffStatusEvent(ctx context.Context, chatID uuid.UUID) { + if api.chatDaemon == nil { + return + } + + if err := api.chatDaemon.PublishDiffStatusChange(ctx, chatID); err != nil { + api.Logger.Debug(ctx, "failed to publish chat diff status change", + slog.F("chat_id", chatID), + slog.Error(err), + ) + } +} + func (api *API) resolveChatDiffContents( ctx context.Context, chat database.Chat, diff --git a/coderd/pubsub/chatevent.go b/coderd/pubsub/chatevent.go index 70ec8ab297..83e49fa64e 100644 --- a/coderd/pubsub/chatevent.go +++ b/coderd/pubsub/chatevent.go @@ -39,8 +39,9 @@ type ChatEvent struct { type ChatEventKind string const ( - ChatEventKindStatusChange ChatEventKind = "status_change" - ChatEventKindTitleChange ChatEventKind = "title_change" - ChatEventKindCreated ChatEventKind = "created" - ChatEventKindDeleted ChatEventKind = "deleted" + ChatEventKindStatusChange ChatEventKind = "status_change" + ChatEventKindTitleChange ChatEventKind = "title_change" + ChatEventKindCreated ChatEventKind = "created" + ChatEventKindDeleted ChatEventKind = "deleted" + ChatEventKindDiffStatusChange ChatEventKind = "diff_status_change" ) diff --git a/site/src/pages/AgentsPage/AgentDetail/ChatContext.ts b/site/src/pages/AgentsPage/AgentDetail/ChatContext.ts index 8b791e01e5..5ef9ba7158 100644 --- a/site/src/pages/AgentsPage/AgentDetail/ChatContext.ts +++ b/site/src/pages/AgentsPage/AgentDetail/ChatContext.ts @@ -1,10 +1,5 @@ import { watchChat } from "api/api"; -import { - chatDiffContentsKey, - chatDiffStatusKey, - chatKey, - chatsKey, -} from "api/queries/chats"; +import { chatKey, chatsKey } from "api/queries/chats"; import type * as TypesGen from "api/typesGenerated"; import { asRecord, asString } from "components/ai-elements/runtimeTypeUtils"; import { @@ -614,7 +609,6 @@ export const useChatStore = ( continue; } - const previousStatus = store.getSnapshot().chatStatus; store.setChatStatus(nextStatus); if (nextStatus === "pending" || nextStatus === "waiting") { store.clearStreamState(); @@ -627,16 +621,6 @@ export const useChatStore = ( status: nextStatus, updated_at: new Date().toISOString(), })); - if (previousStatus !== nextStatus) { - void Promise.all([ - queryClient.invalidateQueries({ - queryKey: chatDiffStatusKey(chatID), - }), - queryClient.invalidateQueries({ - queryKey: chatDiffContentsKey(chatID), - }), - ]); - } continue; } @@ -681,7 +665,6 @@ export const useChatStore = ( cancelScheduledStreamReset, chatID, clearChatErrorReason, - queryClient, scheduleStreamReset, setChatErrorReason, store, diff --git a/site/src/pages/AgentsPage/AgentsPage.tsx b/site/src/pages/AgentsPage/AgentsPage.tsx index 423260d599..7c65459adb 100644 --- a/site/src/pages/AgentsPage/AgentsPage.tsx +++ b/site/src/pages/AgentsPage/AgentsPage.tsx @@ -2,6 +2,8 @@ import { watchChats } from "api/api"; import { getErrorMessage } from "api/errors"; import { archiveChat, + chatDiffContentsKey, + chatDiffStatusKey, chatKey, chatModelConfigs, chatModels, @@ -291,6 +293,21 @@ const AgentsPage: FC = () => { return; } + if (chatEvent.kind === "diff_status_change") { + void Promise.all([ + queryClient.invalidateQueries({ + queryKey: chatsKey, + }), + queryClient.invalidateQueries({ + queryKey: chatDiffStatusKey(updatedChat.id), + }), + queryClient.invalidateQueries({ + queryKey: chatDiffContentsKey(updatedChat.id), + }), + ]); + return; + } + queryClient.setQueryData( chatsKey, (prev: TypesGen.Chat[] | undefined) => {