feat(chat): stop active llm responses

This commit is contained in:
2026-05-02 16:26:10 -04:00
parent b5e60ff0e2
commit f359471a27
11 changed files with 130 additions and 6 deletions

View File

@@ -449,6 +449,32 @@ func (a *API) GetChatStream(w http.ResponseWriter, r *http.Request) {
}
}
func (a *API) StopChatGeneration(w http.ResponseWriter, r *http.Request) {
log := a.logger.WithField("handler", "StopChatGenerationHandler")
// Parse Chat ID
rawChatID := r.PathValue("chatId")
if rawChatID == "" {
log.Error("missing chat ID parameter")
http.Error(w, "Chat ID is required", http.StatusBadRequest)
return
}
chatID, err := uuid.Parse(rawChatID)
if err != nil {
log.WithError(err).Error("invalid chat ID format")
http.Error(w, "Invalid chat ID format", http.StatusBadRequest)
return
}
// Stop Generation
if !a.generationManager.stop(chatID) {
http.Error(w, "Chat generation is not active", http.StatusNotFound)
return
}
w.WriteHeader(http.StatusNoContent)
}
func (a *API) PostChatMessage(w http.ResponseWriter, r *http.Request) {
log := a.logger.WithField("handler", "PostChatMessageHandler")
@@ -563,7 +589,7 @@ func (a *API) startMessageGeneration(chatID uuid.UUID, chatModel, userMessage st
func (a *API) runMessageGeneration(apiClient *client.Client, chat *store.Chat, assistantMsg *store.Message, chatModel string, gen *generation) {
// Create Generation Context
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
ctx, cancel := context.WithTimeout(gen.ctx, time.Minute*5)
defer cancel()
// Send Message
@@ -593,15 +619,37 @@ func (a *API) runMessageGeneration(apiClient *client.Client, chat *store.Chat, a
return nil
}); err != nil {
assistantMsg.Status = store.MessageStatusFailed
// Handle Stopped Generation
if errors.Is(gen.ctx.Err(), context.Canceled) {
assistantMsg.Status = store.MessageStatusStopped
if saveErr := a.store.SaveChatMessage(assistantMsg); saveErr != nil {
a.logger.WithError(saveErr).WithField("chat_id", chat.ID).Error("failed to save stopped assistant message")
}
gen.broadcast(&MessageChunk{AssistantMessage: assistantMsg})
return
}
// Handle Error Generation
assistantMsg.Status = store.MessageStatusError
if saveErr := a.store.SaveChatMessage(assistantMsg); saveErr != nil {
a.logger.WithError(saveErr).WithField("chat_id", chat.ID).Error("failed to save failed assistant message")
a.logger.WithError(saveErr).WithField("chat_id", chat.ID).Error("failed to save errored assistant message")
}
gen.broadcast(&MessageChunk{AssistantMessage: assistantMsg})
a.logger.WithError(err).WithField("chat_id", chat.ID).Error("failed to generate text stream")
return
}
// Handle Stopped Generation
if errors.Is(gen.ctx.Err(), context.Canceled) {
assistantMsg.Status = store.MessageStatusStopped
if err := a.store.SaveChatMessage(assistantMsg); err != nil {
a.logger.WithError(err).WithField("chat_id", chat.ID).Error("failed to save stopped assistant message")
return
}
gen.broadcast(&MessageChunk{AssistantMessage: assistantMsg})
return
}
// Summarize & Update Chat Title
if chat.Title == "" {
var err error