Files
nvfp4_gguf_quant/llama.cpp/tools/ui/tests/client/models-sidecar-badges.svelte.test.ts
T

109 lines
3.5 KiB
TypeScript

// Guards the draft badges a model row shows: a registered model records its draft
// in its `--model-draft` args, which know the file's quant, and the listing reports
// the kinds every cached model of the repo has on disk, which do not. The row shows
// each kind once, and two quants of one repo keep their own drafts apart.
import { ModelAuxSidecar, ModelDraftSidecar, ServerModelStatus } from '$lib/enums';
import { modelsStore } from '$lib/stores';
import type { ApiModelDataEntry } from '$lib/types/api';
import { beforeEach, describe, expect, it } from 'vitest';
const REPO = 'ggml-org/Qwen3.8-Flash-Next-GGUF';
/** Draft file of a cached model, as a preset records it in `--model-draft`. */
function draftPath(quant: string): string {
return `/cache/models--ggml-org--Qwen3.8-Flash-Next-GGUF/snapshots/${'a'.repeat(40)}/mtp-Qwen3.8-Flash-Next-${quant}.gguf`;
}
/** A router entry; `args` stand in for the args of a loaded instance. */
function entry(
id: string,
sidecars: string[] = [],
args: string[] = [],
status = ServerModelStatus.UNLOADED
) {
return {
created: 0,
id,
in_cache: true,
object: 'model',
owned_by: 'llamacpp',
path: `/models/${id}`,
sidecars,
status: { args, value: status }
} as unknown as ApiModelDataEntry;
}
describe('draft sidecar badges', () => {
beforeEach(() => {
modelsStore.routerModels = [];
});
it('shows one badge for a draft the args and the listing both report', () => {
modelsStore.routerModels = [
entry(
`${REPO}:Q8_0`,
[ModelAuxSidecar.MMPROJ, ModelDraftSidecar.MTP],
['--model-draft', draftPath('Q8_0')]
)
];
// the args badge wins: it knows the quant the listing does not
expect(modelsStore.status.getDraftSidecars(`${REPO}:Q8_0`)).toEqual([
{ kind: ModelDraftSidecar.MTP, quant: 'Q8_0', repo: REPO }
]);
});
it('gives each quant of a repo the draft it pulls itself', () => {
modelsStore.routerModels = [
entry(`${REPO}:IQ4_NL`, [], ['--model-draft', draftPath('Q4_0')]),
entry(`${REPO}:Q8_0`, [], ['--model-draft', draftPath('Q8_0')])
];
expect(modelsStore.status.getDraftSidecars(`${REPO}:IQ4_NL`)).toEqual([
{ kind: ModelDraftSidecar.MTP, quant: 'Q4_0', repo: REPO }
]);
expect(modelsStore.status.getDraftSidecars(`${REPO}:Q8_0`)).toEqual([
{ kind: ModelDraftSidecar.MTP, quant: 'Q8_0', repo: REPO }
]);
});
it('shows one badge for a kind two cached quants report', () => {
modelsStore.routerModels = [
entry(`${REPO}:IQ4_NL`, [ModelDraftSidecar.MTP]),
entry(`${REPO}:Q8_0`, [ModelDraftSidecar.MTP])
];
expect(modelsStore.status.getDraftSidecars(`${REPO}:IQ4_NL`)).toEqual([
{ kind: ModelDraftSidecar.MTP, quant: null, repo: REPO }
]);
});
it('marks the drafts of a download on its way as pending', () => {
modelsStore.routerModels = [
entry(
`${REPO}:Q4_0`,
[ModelAuxSidecar.MMPROJ, ModelDraftSidecar.MTP],
[],
ServerModelStatus.DOWNLOADING
)
];
// the kinds are not on disk yet, so the row reads them as in flight
expect(modelsStore.status.getDraftSidecars(`${REPO}:Q4_0`)).toEqual([
{ kind: ModelDraftSidecar.MTP, pending: true, quant: null, repo: REPO }
]);
});
it('keeps the on-disk badge of a kind a download also pulls', () => {
modelsStore.routerModels = [
entry(`${REPO}:IQ4_NL`, [ModelDraftSidecar.MTP], [], ServerModelStatus.INCOMPLETE),
entry(`${REPO}:Q8_0`, [], ['--model-draft', draftPath('Q8_0')])
];
expect(modelsStore.status.getDraftSidecars(`${REPO}:Q8_0`)).toEqual([
{ kind: ModelDraftSidecar.MTP, quant: 'Q8_0', repo: REPO }
]);
});
});