|
7 | 7 | interfaceSchema, |
8 | 8 | fileStorageSchema, |
9 | 9 | fileStrategiesSchema, |
| 10 | + summarizationTriggerSchema, |
| 11 | + summarizationConfigSchema, |
10 | 12 | } from '../src/config'; |
11 | 13 | import { tModelSpecPresetSchema, EModelEndpoint } from '../src/schemas'; |
12 | 14 | import { FileSources } from '../src/types/files'; |
@@ -502,3 +504,109 @@ describe('interfaceSchema', () => { |
502 | 504 | expect(result.modelSelect).toBe(false); |
503 | 505 | }); |
504 | 506 | }); |
| 507 | + |
| 508 | +describe('summarizationTriggerSchema', () => { |
| 509 | + it.each([ |
| 510 | + ['token_ratio', 0.8], |
| 511 | + ['remaining_tokens', 500], |
| 512 | + ['messages_to_refine', 4], |
| 513 | + ] as const)('accepts documented trigger type "%s" with a sensible value', (type, value) => { |
| 514 | + const result = summarizationTriggerSchema.safeParse({ type, value }); |
| 515 | + expect(result.success).toBe(true); |
| 516 | + }); |
| 517 | + |
| 518 | + it('rejects the legacy/typoed "token_count" trigger type', () => { |
| 519 | + const result = summarizationTriggerSchema.safeParse({ |
| 520 | + type: 'token_count', |
| 521 | + value: 8000, |
| 522 | + }); |
| 523 | + expect(result.success).toBe(false); |
| 524 | + }); |
| 525 | + |
| 526 | + it('rejects unknown trigger types', () => { |
| 527 | + const result = summarizationTriggerSchema.safeParse({ |
| 528 | + type: 'never_heard_of_it', |
| 529 | + value: 1, |
| 530 | + }); |
| 531 | + expect(result.success).toBe(false); |
| 532 | + }); |
| 533 | + |
| 534 | + it('rejects negative values on any trigger type', () => { |
| 535 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: -0.5 }).success).toBe( |
| 536 | + false, |
| 537 | + ); |
| 538 | + expect( |
| 539 | + summarizationTriggerSchema.safeParse({ type: 'remaining_tokens', value: -1 }).success, |
| 540 | + ).toBe(false); |
| 541 | + expect( |
| 542 | + summarizationTriggerSchema.safeParse({ type: 'messages_to_refine', value: -1 }).success, |
| 543 | + ).toBe(false); |
| 544 | + }); |
| 545 | + |
| 546 | + it('rejects zero for count-based triggers where it has no meaningful effect', () => { |
| 547 | + expect( |
| 548 | + summarizationTriggerSchema.safeParse({ type: 'remaining_tokens', value: 0 }).success, |
| 549 | + ).toBe(false); |
| 550 | + expect( |
| 551 | + summarizationTriggerSchema.safeParse({ type: 'messages_to_refine', value: 0 }).success, |
| 552 | + ).toBe(false); |
| 553 | + }); |
| 554 | + |
| 555 | + it('rejects token_ratio values > 1 to catch the "80 meant as 80%" mistake', () => { |
| 556 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: 80 }).success).toBe( |
| 557 | + false, |
| 558 | + ); |
| 559 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: 1.01 }).success).toBe( |
| 560 | + false, |
| 561 | + ); |
| 562 | + }); |
| 563 | + |
| 564 | + it('accepts token_ratio values at the inclusive 0 and 1 bounds per docs', () => { |
| 565 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: 0 }).success).toBe( |
| 566 | + true, |
| 567 | + ); |
| 568 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: 1 }).success).toBe( |
| 569 | + true, |
| 570 | + ); |
| 571 | + }); |
| 572 | + |
| 573 | + it('allows remaining_tokens and messages_to_refine values above 1 (token/message counts)', () => { |
| 574 | + expect( |
| 575 | + summarizationTriggerSchema.safeParse({ type: 'remaining_tokens', value: 2000 }).success, |
| 576 | + ).toBe(true); |
| 577 | + expect( |
| 578 | + summarizationTriggerSchema.safeParse({ type: 'messages_to_refine', value: 20 }).success, |
| 579 | + ).toBe(true); |
| 580 | + }); |
| 581 | + |
| 582 | + it('rejects non-finite values (Infinity, NaN) for every trigger type', () => { |
| 583 | + for (const type of ['token_ratio', 'remaining_tokens', 'messages_to_refine'] as const) { |
| 584 | + expect(summarizationTriggerSchema.safeParse({ type, value: Infinity }).success).toBe(false); |
| 585 | + expect(summarizationTriggerSchema.safeParse({ type, value: -Infinity }).success).toBe(false); |
| 586 | + expect(summarizationTriggerSchema.safeParse({ type, value: NaN }).success).toBe(false); |
| 587 | + } |
| 588 | + }); |
| 589 | + |
| 590 | + it('requires integer values for count-based triggers', () => { |
| 591 | + expect( |
| 592 | + summarizationTriggerSchema.safeParse({ type: 'remaining_tokens', value: 500.5 }).success, |
| 593 | + ).toBe(false); |
| 594 | + expect( |
| 595 | + summarizationTriggerSchema.safeParse({ type: 'messages_to_refine', value: 2.5 }).success, |
| 596 | + ).toBe(false); |
| 597 | + }); |
| 598 | + |
| 599 | + it('still allows fractional values for token_ratio', () => { |
| 600 | + expect(summarizationTriggerSchema.safeParse({ type: 'token_ratio', value: 0.8 }).success).toBe( |
| 601 | + true, |
| 602 | + ); |
| 603 | + }); |
| 604 | + |
| 605 | + it('parses inside the full summarization config', () => { |
| 606 | + const result = summarizationConfigSchema.safeParse({ |
| 607 | + enabled: true, |
| 608 | + trigger: { type: 'token_ratio', value: 0.8 }, |
| 609 | + }); |
| 610 | + expect(result.success).toBe(true); |
| 611 | + }); |
| 612 | +}); |
0 commit comments