/** * Unit tests for the finish-reason detection helpers. * * Guards the single source of truth that truncation-aware callers * (Graph.ts sticky finish reason, host continuation retry) rely on. */ import { TRUNCATION_FINISH_REASONS, isTruncationReason, } from '../finishReasons'; describe('TRUNCATION_FINISH_REASONS', () => { it('includes every provider-specific truncation value we support', () => { expect(TRUNCATION_FINISH_REASONS.has('max_tokens')).toBe(true); expect(TRUNCATION_FINISH_REASONS.has('length')).toBe(true); expect(TRUNCATION_FINISH_REASONS.has('MAX_TOKENS')).toBe(true); }); it('is case-sensitive — lowercase vertex value is not accepted', () => { // VertexAI uses the uppercase enum name; lowercase would be a wire bug // we do not want to silently treat as truncation. expect(TRUNCATION_FINISH_REASONS.has('max_Tokens')).toBe(false); }); }); describe('isTruncationReason', () => { it('returns true for Anthropic/Bedrock max_tokens', () => { expect(isTruncationReason('max_tokens')).toBe(true); }); it('returns true for OpenAI length', () => { expect(isTruncationReason('length')).toBe(true); }); it('returns true for VertexAI MAX_TOKENS', () => { expect(isTruncationReason('MAX_TOKENS')).toBe(true); }); it('returns false for the stop/end_turn happy path', () => { expect(isTruncationReason('stop')).toBe(false); expect(isTruncationReason('end_turn')).toBe(false); expect(isTruncationReason('STOP')).toBe(false); }); it('returns false for tool_use / tool_calls', () => { expect(isTruncationReason('tool_use')).toBe(false); expect(isTruncationReason('tool_calls')).toBe(false); }); it('returns false for undefined, null, and empty string', () => { expect(isTruncationReason(undefined)).toBe(false); expect(isTruncationReason(null)).toBe(false); expect(isTruncationReason('')).toBe(false); }); });