From dec06a839599ea02b1416b9e13344dee0253ceed Mon Sep 17 00:00:00 2001 From: Aleksander Grygier Date: Tue, 29 Sep 2026 13:44:11 +0200 Subject: [PATCH] ui : cover the memory-fit and tool-use heuristics in tests Assisted-by: pi:zai-org/GLM-5.3-Flash --- .../model-compatibility.constants.ts | 2 +- .../ui/tests/unit/model-compatibility.test.ts | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tools/ui/tests/unit/model-compatibility.test.ts diff --git a/tools/ui/src/lib/constants/model-compatibility.constants.ts b/tools/ui/src/lib/constants/model-compatibility.constants.ts index 327e41f81b..5d65f8d62e 100644 --- a/tools/ui/src/lib/constants/model-compatibility.constants.ts +++ b/tools/ui/src/lib/constants/model-compatibility.constants.ts @@ -11,7 +11,7 @@ /** Bytes in one mebibyte (MiB), used to convert a file size to MB. */ export const MIB_BYTES = 1_048_576; -/** MB in one GB. */ +/** MiB in one tier unit; the tiers below are binary sizes, i.e. GiB. */ export const MB_PER_GB = 1024; /** Overhead multiplier applied to the file size when estimating weight memory. */ diff --git a/tools/ui/tests/unit/model-compatibility.test.ts b/tools/ui/tests/unit/model-compatibility.test.ts new file mode 100644 index 0000000000..0fbd1e39e0 --- /dev/null +++ b/tools/ui/tests/unit/model-compatibility.test.ts @@ -0,0 +1,44 @@ +import { detectToolUseSupport } from '$lib/utils/chat-template-tool-detector'; +import { minMemoryTierGb } from '$lib/utils/model-compatibility'; +import { describe, expect, it } from 'vitest'; + +describe('minMemoryTierGb', () => { + it('picks the smallest tier whose budget fits the file', () => { + // budget(16) = 16 * 1024 * 0.75 - 2048 = 10240 MiB; ~9.2 GiB file fits + expect(minMemoryTierGb(9.5 * 1024 * 1024 * 1024)).toBe(16); + // budget(12) = 7168 MiB; the same file does not fit + expect(minMemoryTierGb(9.5 * 1024 * 1024 * 1024)).not.toBe(12); + }); + + it('applies the quant headroom to the file size', () => { + // exactly the tier-32 budget before the 1.05 headroom; with it the file + // spills into the next tier + const budget32Mb = 32 * 1024 * 0.75 - 2048; + const bytes = (budget32Mb / 1.05) * 1024 * 1024; + + expect(minMemoryTierGb(bytes)).toBe(32); + expect(minMemoryTierGb(bytes + 1)).toBe(48); + }); + + it('returns null for empty sizes and over-budget files', () => { + expect(minMemoryTierGb(0)).toBeNull(); + expect(minMemoryTierGb(4 * 1024 * 1024 * 1024 * 1024)).toBeNull(); + }); +}); + +describe('detectToolUseSupport', () => { + it('detects the jinja tools variable', () => { + expect(detectToolUseSupport('{% for tool in tools %}')).toBe(true); + expect(detectToolUseSupport('{{ tools | tojson }}')).toBe(true); + }); + + it('detects tool-call tokens case-insensitively', () => { + expect(detectToolUseSupport('WRITES BLOCKS')).toBe(true); + expect(detectToolUseSupport('emits Tool_Call sections')).toBe(true); + }); + + it('rejects templates without tool references', () => { + expect(detectToolUseSupport('')).toBe(false); + expect(detectToolUseSupport('{{ prompt }}')).toBe(false); + }); +});