| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | |
| 7 | "reasonix/internal/event" |
| 8 | "reasonix/internal/provider" |
| 9 | "reasonix/internal/tool" |
| 10 | ) |
| 11 | |
| 12 | // A retry aggregate is billable tokens, not context shape. Reporting it would |
| 13 | // show pressure that the model never actually saw. |
| 14 | func TestContextReportUsesLatestPromptNotBillableAggregate(t *testing.T) { |
| 15 | sess := NewSession("sys") |
| 16 | sess.Add(provider.Message{Role: provider.RoleUser, Content: strings.Repeat("x", 400)}) |
| 17 | a := New(&fakeProvider{reply: "unused"}, tool.NewRegistry(), sess, Options{ |
| 18 | ContextWindow: 100_000, RecentKeep: 2, |
| 19 | }, event.Discard) |
| 20 | |
| 21 | a.sess.output.lastUsage.Store(&provider.Usage{ |
| 22 | PromptTokens: 363_000, // three recovery attempts, billed |
| 23 | ContextPromptTokens: 122_000, // what the last request actually carried |
| 24 | RequestCount: 3, |
| 25 | }) |
| 26 | |
| 27 | if got := a.ContextReport().LatestPrompt; got != 122_000 { |
| 28 | t.Errorf("LatestPrompt = %d, want 122000 (the latest request, not the billed aggregate)", got) |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | // The sole trigger must come from the same helper the decision uses. |
| 33 | func TestContextReportThresholdsMatchTheDecision(t *testing.T) { |
| 34 | a := New(&fakeProvider{reply: "unused"}, tool.NewRegistry(), NewSession("sys"), Options{ |
| 35 | ContextWindow: 200_000, CompactRatio: 0.85, RecentKeep: 2, |
| 36 | }, event.Discard) |
| 37 | |
| 38 | rep := a.ContextReport() |
| 39 | fold := a.compactTrigger() |
| 40 | if rep.FoldThreshold != fold { |
| 41 | t.Errorf("report FoldThreshold %d differs from compactTrigger %d", rep.FoldThreshold, fold) |
| 42 | } |
| 43 | if rep.SoftThreshold != 0 || rep.SnipThreshold != 0 || rep.ForceThreshold != 0 { |
| 44 | t.Errorf("legacy multi-threshold fields should stay zero: soft=%d snip=%d force=%d", |
| 45 | rep.SoftThreshold, rep.SnipThreshold, rep.ForceThreshold) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | // A zero window disables maintenance; the thresholds then mean nothing and must |
| 50 | // not be presented as if they did. |
| 51 | func TestContextReportLeavesThresholdsZeroWhenDisabled(t *testing.T) { |
| 52 | a := New(&fakeProvider{reply: "unused"}, tool.NewRegistry(), NewSession("sys"), Options{ |
| 53 | ContextWindow: 0, RecentKeep: 2, |
| 54 | }, event.Discard) |
| 55 | |
| 56 | rep := a.ContextReport() |
| 57 | if rep.Window != 0 || rep.FoldThreshold != 0 || rep.ForceThreshold != 0 { |
| 58 | t.Errorf("disabled maintenance reported thresholds: %+v", rep) |
| 59 | } |
| 60 | } |
| 61 |