From 867afefb088f3dfa6ac0771317b33fc98793ca4c Mon Sep 17 00:00:00 2001 From: Mathias Date: Thu, 1 Oct 2026 16:56:51 +0200 Subject: [PATCH] test(chat): a request may carry its own transcript budget (red) The 18,000-char default is ~22 min of speech and keeps only the head; an uploaded hour is ~50,000 chars. Red: Request.MaxChars is undefined. Co-Authored-By: Claude Sonnet 5.5 --- internal/adapters/chat/maxchars_test.go | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 internal/adapters/chat/maxchars_test.go diff --git a/internal/adapters/chat/maxchars_test.go b/internal/adapters/chat/maxchars_test.go new file mode 100644 index 0000000..f3f9541 --- /dev/null +++ b/internal/adapters/chat/maxchars_test.go @@ -0,0 +1,53 @@ +package chat + +import ( + "context" + "strings" + "testing" +) + +// A Request may carry its own transcript budget. The Service's cap (18,000 chars by +// default) is sized for YouTube captions; an uploaded recording is much longer +// (~50,000 chars an hour), and keeping only the head of it would answer questions +// about the last two-thirds of a meeting from text that does not contain them +// (ADR-033). The per-request value overrides; zero means "the service default". + +func TestAnswerMaxCharsOverridesTheServiceCap(t *testing.T) { + tests := []struct { + name string + serviceCap int + requestCap int + transcriptLen int + wantKept int + wantTruncated bool + }{ + {"request cap above the service cap keeps the whole transcript", 10, 100, 50, 50, false}, + {"request cap below the service cap bounds tighter", 100, 10, 50, 10, true}, + {"zero request cap falls back to the service cap", 20, 0, 50, 20, true}, + {"negative request cap is treated as unset", 20, -1, 50, 20, true}, + {"request cap exceeded is reported as truncated", 10, 30, 50, 30, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := &factory{answer: "answer"} + s := New(f.make, []string{"koala/phi4-mini"}, tt.serviceCap) + + reply, err := s.Answer(context.Background(), Request{ + Model: "koala/phi4-mini", + Transcript: strings.Repeat("x", tt.transcriptLen), + Question: "what was decided?", + MaxChars: tt.requestCap, + }) + + if err != nil { + t.Fatalf("Answer: %v", err) + } + if got := strings.Count(f.used.lastSystem, "x"); got != tt.wantKept { + t.Errorf("transcript chars sent = %d, want %d", got, tt.wantKept) + } + if reply.Truncated != tt.wantTruncated { + t.Errorf("Truncated = %v, want %v", reply.Truncated, tt.wantTruncated) + } + }) + } +}