TestPackAnchorsUserTaskOverBudget: a long single turn (one small task message, then many large assistant rounds that fill the budget) would let the newest-first walk evict the sole user task, leaving a userless window that 400s every OpenAI-compat backend ("no user query found in messages"). Pack mu
(t *testing.T)
| 481 | } |
| 482 | |
| 483 | // TestPackAnchorsUserTaskOverBudget: a long single turn (one small task message, |
| 484 | // then many large assistant rounds that fill the budget) would let the |
| 485 | // newest-first walk evict the sole user task, leaving a userless window that |
| 486 | // 400s every OpenAI-compat backend ("no user query found in messages"). Pack |
| 487 | // must re-anchor the original task over budget so the wire always carries it. |
| 488 | func TestPackAnchorsUserTaskOverBudget(t *testing.T) { |
| 489 | big := strings.Repeat("x", 4*3000) // ~3000-token assistant chunk |
| 490 | history := []Message{ |
| 491 | {Role: RoleUser, Content: "BUILD THE GALAXY"}, |
| 492 | {Role: RoleAssistant, Content: big}, |
| 493 | {Role: RoleAssistant, Content: big}, |
| 494 | {Role: RoleAssistant, Content: big}, |
| 495 | } |
| 496 | r := Pack(history, 5000) // holds ~1 assistant chunk; the task gets evicted |
| 497 | var sawTask bool |
| 498 | for _, m := range r.Messages { |
| 499 | if m.Role == RoleUser && m.Content == "BUILD THE GALAXY" { |
| 500 | sawTask = true |
| 501 | } |
| 502 | } |
| 503 | if !sawTask { |
| 504 | t.Fatalf("original user task was evicted, leaving a userless window: %+v", r.Messages) |
| 505 | } |
| 506 | // Chronological order: the anchored task must lead the window. |
| 507 | if r.Messages[0].Role != RoleUser { |
| 508 | t.Fatalf("anchored task not first: %+v", r.Messages) |