import { afterEach, expect, test } from 'bun:test' import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { TerminalProgress } from '../src/cli/progress.js' const directories: string[] = [] afterEach(async () => { await Promise.all(directories.splice(0).map((path) => rm(path, { recursive: true, force: true }))) }) async function setup(cached: boolean) { const cacheDir = await mkdtemp(join(tmpdir(), 'decide-progress-')) directories.push(cacheDir) if (cached) { const root = join(cacheDir, 'dizyann/crivo-150m-web') await mkdir(join(root, 'onnx'), { recursive: true }) await Promise.all( ['config.json', 'tokenizer.json', 'tokenizer_config.json', 'onnx/model_quantized.onnx'].map( (file) => writeFile(join(root, file), 'cached test fixture') ) ) } const lines: string[] = [] const reporter = new TerminalProgress((line) => lines.push(line)) await reporter.loading({ modelId: 'dizyann/crivo-150m-web', dtype: 'q8', providers: ['cpu'], cacheDir }) return { reporter, lines, cacheDir } } test('announces missing downloads and size before receiving progress', async () => { const { reporter, lines } = await setup(false) expect(lines.join('\n')).toContain('download required') expect(lines.join('\n')).toContain('144 MiB') reporter.progress({ status: 'progress', file: 'onnx/model_quantized.onnx', progress: 12 }) reporter.progress({ status: 'progress', file: 'onnx/model_quantized.onnx', progress: 15 }) reporter.progress({ status: 'progress', file: 'onnx/model_quantized.onnx', progress: 29 }) expect(lines.filter((line) => line.startsWith('Downloading'))).toEqual([ 'Downloading onnx/model_quantized.onnx: 10%', 'Downloading onnx/model_quantized.onnx: 20%' ]) }) test('does not label cached reads as downloads and reports execution metrics', async () => { const { reporter, lines } = await setup(true) reporter.progress({ status: 'download', file: 'tokenizer.json' }) reporter.progress({ status: 'progress', file: 'tokenizer.json', progress: 100 }) expect(lines.join('\n')).toContain('Files found in cache') expect(lines.join('\n')).not.toContain('Downloading') reporter.summary({ loadMs: 1000, inferenceMs: 250, disposeMs: 20 }, 3) expect(lines.join('\n')).toContain('3 decisions') expect(lines.join('\n')).toContain('inference: 0.25 s') expect(lines.join('\n')).toContain('providers: cpu') }) test('announces a missing external weight shard even when the graph is cached', async () => { const { reporter, lines, cacheDir } = await setup(true) lines.length = 0 await reporter.loading({ modelId: 'dizyann/crivo-150m-web', dtype: 'q8', providers: ['cpu'], cacheDir, weightMiB: 987, weightFiles: ['onnx/model_quantized.onnx', 'onnx/model_quantized.onnx_data'] }) expect(lines.join('\n')).toContain('download required') expect(lines.join('\n')).toContain('987 MiB') expect(lines.find((line) => line.startsWith('Download:'))).toBe( 'Download: onnx/model_quantized.onnx_data' ) })