From 4bd2cddfee45bb072623c68a9e5cd4efc138488c Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Mon, 25 Aug 2025 15:08:52 -0300 Subject: [PATCH] fix: fix `panic` that happens on `crush run` with tool calls We need to track the number of read bytes per message. Fixes #871 --- internal/app/app.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index c8f6fe75ed2db719fa7ace6d9507f46fd2b441f3..c2bfb0ebd027388146b9745cb3fbc69a514336ed 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -154,7 +154,7 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool } messageEvents := app.Messages.Subscribe(ctx) - readBts := 0 + messageReadBytes := make(map[string]int) for { select { @@ -170,11 +170,14 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool } msgContent := result.Message.Content().String() + readBts := messageReadBytes[result.Message.ID] + if len(msgContent) < readBts { slog.Error("Non-interactive: message content is shorter than read bytes", "message_length", len(msgContent), "read_bytes", readBts) return fmt.Errorf("message content is shorter than read bytes: %d < %d", len(msgContent), readBts) } fmt.Println(msgContent[readBts:]) + messageReadBytes[result.Message.ID] = len(msgContent) slog.Info("Non-interactive: run completed", "session_id", sess.ID) return nil @@ -183,9 +186,18 @@ func (app *App) RunNonInteractive(ctx context.Context, prompt string, quiet bool msg := event.Payload if msg.SessionID == sess.ID && msg.Role == message.Assistant && len(msg.Parts) > 0 { stopSpinner() - part := msg.Content().String()[readBts:] + + content := msg.Content().String() + readBytes := messageReadBytes[msg.ID] + + if len(content) < readBytes { + slog.Error("Non-interactive: message content is shorter than read bytes", "message_length", len(content), "read_bytes", readBytes) + return fmt.Errorf("message content is shorter than read bytes: %d < %d", len(content), readBytes) + } + + part := content[readBytes:] fmt.Print(part) - readBts += len(part) + messageReadBytes[msg.ID] = len(content) } case <-ctx.Done():