diff --git a/coderd/chatd/chatd.go b/coderd/chatd/chatd.go index 3476e68bb5..06fa5b7f8d 100644 --- a/coderd/chatd/chatd.go +++ b/coderd/chatd/chatd.go @@ -1741,10 +1741,10 @@ func (p *Server) processChat(ctx context.Context, chat database.Chat) { // changes made during processing (e.g. AI-generated titles // from maybeGenerateChatTitle). The local `chat` variable // is a value copy and won't reflect updates made in runChat. - if freshChat, readErr := p.db.GetChatByID(ctx, chat.ID); readErr == nil { + if freshChat, readErr := p.db.GetChatByID(cleanupCtx, chat.ID); readErr == nil { chat = freshChat } else { - logger.Warn(ctx, "failed to re-read chat for status event", + logger.Warn(cleanupCtx, "failed to re-read chat for status event", slog.F("chat_id", chat.ID), slog.Error(readErr)) } chat.Status = status @@ -1816,7 +1816,11 @@ func (p *Server) runChat( // Fire title generation asynchronously so it doesn't block the // chat response. It uses a detached context so it can finish // even after the chat processing context is canceled. - go p.maybeGenerateChatTitle(context.WithoutCancel(ctx), chat, messages, model, logger) + p.inflight.Add(1) + go func() { + defer p.inflight.Done() + p.maybeGenerateChatTitle(context.WithoutCancel(ctx), chat, messages, model, logger) + }() prompt, err := chatprompt.ConvertMessages(messages) if err != nil { diff --git a/site/src/api/queries/chats.ts b/site/src/api/queries/chats.ts index 1065204723..43f6ade2db 100644 --- a/site/src/api/queries/chats.ts +++ b/site/src/api/queries/chats.ts @@ -8,6 +8,7 @@ export const chatKey = (chatId: string) => ["chats", chatId] as const; export const chats = () => ({ queryKey: chatsKey, queryFn: () => API.getChats(), + refetchOnWindowFocus: true as const, }); export const chat = (chatId: string) => ({ diff --git a/site/src/pages/AgentsPage/AgentsPage.tsx b/site/src/pages/AgentsPage/AgentsPage.tsx index 4d27543e59..efe3fcd764 100644 --- a/site/src/pages/AgentsPage/AgentsPage.tsx +++ b/site/src/pages/AgentsPage/AgentsPage.tsx @@ -267,6 +267,15 @@ const AgentsPage: FC = () => { useEffect(() => { const ws = watchChats(); + ws.addEventListener("open", () => { + void queryClient.invalidateQueries({ queryKey: chatsKey }); + }); + ws.addEventListener("close", () => { + void queryClient.invalidateQueries({ queryKey: chatsKey }); + }); + ws.addEventListener("error", () => { + void queryClient.invalidateQueries({ queryKey: chatsKey }); + }); ws.addEventListener("message", (event) => { const sse = event.parsedMessage; if (sse?.type !== "data" || !sse.data) {