From 2f039462382f215d100c82027ef13341b4df879c Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Tue, 3 Nov 2026 08:25:37 +0000 Subject: [PATCH] fix(studio): bound the model call of a compaction A compaction ran on a context with no deadline, so a model that never answered held the chat busy for good. Give it a 10 minute limit. Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto --- core/services/studio/chatcommands.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/services/studio/chatcommands.go b/core/services/studio/chatcommands.go index 5abf772ee..af0bba7bd 100644 --- a/core/services/studio/chatcommands.go +++ b/core/services/studio/chatcommands.go @@ -260,6 +260,9 @@ func (s *Service) contextCommand(ctx context.Context, p, conv string, fn func(re return err } +// compactLimit bounds the model call of a compaction. +const compactLimit = 10 * time.Minute + // Compact shrinks the model's context of the chat now, with the summary the // loop makes when the context fills up, and returns its size in tokens before // and after. The transcript keeps every message and gets a marker; the next @@ -281,7 +284,10 @@ func (s *Service) Compact(ctx context.Context, user, conv string) (before, after s.log.Warn("studio: could not close the chat after a compaction", "chat", conv, "error", cerr) } }() - before, after, err = chat.Compact(context.WithoutCancel(ctx)) + // The summary is one model call that outlives the request; bound it. + cctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), compactLimit) + defer cancel() + before, after, err = chat.Compact(cctx) switch { case errors.Is(err, session.ErrNothingToCompact): return ErrNothingToCompact