/** * Per-tier text + embedding bundle resolution. * * For every Eliza-1 tier, asserts that: * - the catalog entry resolves (and is visible/not hidden), * - the bundle's text GGUF path is declared (per-tier `textFile`), * - the bundle's embedding GGUF path is declared on tiers that have a * dedicated 1024-dim Matryoshka region (2b/4b/9b/27b/27b-256k), * - the bundle's drafter GGUF path is declared only after the hosted * Gemma MTP companion exists, * - the HuggingFace resolve URL for the text and embedding components * resolves to `elizaos/eliza-1` and includes the expected * per-tier prefix. * * Why this matters: the publish pipeline stages a bundle per tier; if a * tier loses its embedding region (or a MTP tier's drafter is renamed), the * runtime's `useModel(TEXT_EMBEDDING, ...)` falls through to a non-local * provider on the desktop path. This test pins the per-tier components * catalogue as a single source of truth and prevents the runtime from * chasing missing MTP drafter files. * * On the 2b entry tier the embedding model is the text backbone pooled with * `--pooling last` (see `services/voice/embedding.ts`), so the catalog * does NOT declare a `components.embedding`. The test mirrors that * exception explicitly. */ import { describe, expect, it } from "vitest"; import { buildHuggingFaceResolveUrlForPath, ELIZA_1_HOSTED_MTP_TIER_IDS, ELIZA_1_HF_REPO, ELIZA_1_TIER_IDS, findCatalogModel, } from "../src/services/catalog.ts"; /** * Tiers that don't ship a dedicated 1024-dim Matryoshka embedding region — * embeddings on these tiers are served by pooling the text backbone with * `--pooling last` via a lazily-started llama-server embedding sidecar * (see `services/voice/embedding-server.ts`). Today this is only * `eliza-1-2b` (the smallest/entry tier, where carrying a separate embedding * GGUF would blow the RAM budget on the small phones it targets). * Every other tier ships `embedding/eliza-1-embedding.gguf` in the * bundle. */ const TIERS_WITHOUT_DEDICATED_EMBEDDING: ReadonlySet = new Set([ "eliza-1-2b", ]); const HOSTED_MTP_TIERS: ReadonlySet = new Set( ELIZA_1_HOSTED_MTP_TIER_IDS, ); describe("per-tier text + embedding bundle resolution", () => { for (const tierId of ELIZA_1_TIER_IDS) { describe(tierId, () => { const model = findCatalogModel(tierId); it("resolves to a visible catalog entry", () => { expect(model, `${tierId} missing from MODEL_CATALOG`).toBeTruthy(); expect(model?.hiddenFromCatalog).not.toBe(true); }); it("declares a text GGUF component on `sourceModel.components.text`", () => { expect(model?.sourceModel?.components.text).toBeTruthy(); expect(model?.sourceModel?.components.text?.repo).toBe( ELIZA_1_HF_REPO, ); expect(model?.sourceModel?.components.text?.file).toMatch( /^bundles\/.+\/text\/eliza-1-.+\.gguf$/, ); }); it("declares a separate-drafter MTP component only for hosted MTP tiers", () => { if (!HOSTED_MTP_TIERS.has(tierId)) { expect(model?.sourceModel?.components.mtp).toBeUndefined(); expect(model?.runtime?.mtp).toBeUndefined(); return; } // Separate-drafter MTP is enabled only after the tier's hosted // Gemma drafter GGUF is present under `mtp/drafter-.gguf`. const slug = tierId.slice("eliza-1-".length); expect(model?.sourceModel?.components.mtp?.repo).toBe( ELIZA_1_HF_REPO, ); expect(model?.sourceModel?.components.mtp?.file).toBe( `bundles/${slug}/mtp/drafter-${slug}.gguf`, ); expect(model?.runtime?.mtp?.specType).toBe("draft-mtp"); expect(model?.runtime?.mtp?.drafterFile).toBe( `mtp/drafter-${slug}.gguf`, ); }); it("declares the embedding GGUF component on tiers that ship a dedicated 1024-dim region", () => { const components = model?.sourceModel?.components; if (TIERS_WITHOUT_DEDICATED_EMBEDDING.has(tierId)) { // 2b serves embeddings by pooling the text backbone. expect(components?.embedding).toBeUndefined(); } else { expect(components?.embedding).toBeTruthy(); expect(components?.embedding?.repo).toBe(ELIZA_1_HF_REPO); // One canonical embedding file per tier — the catalog uses // a single filename for every tier that ships one. expect(components?.embedding?.file).toBe( `bundles/${tierId.slice("eliza-1-".length)}/embedding/eliza-1-embedding.gguf`, ); } }); it("resolves the text component to a HuggingFace URL on elizaos/eliza-1", () => { const file = model?.sourceModel?.components.text?.file; expect(file).toBeTruthy(); if (!model || !file) return; const url = buildHuggingFaceResolveUrlForPath(model, file); expect(url).toContain(`/${ELIZA_1_HF_REPO}/resolve/main/`); expect(url).toContain(`bundles/${tierId.slice("eliza-1-".length)}/`); expect(url).toMatch(/\.gguf\?download=true$/); }); it("resolves the embedding component to a HuggingFace URL when a dedicated region is declared", () => { if (TIERS_WITHOUT_DEDICATED_EMBEDDING.has(tierId)) return; const file = model?.sourceModel?.components.embedding?.file; expect(file).toBeTruthy(); if (!model || !file) return; const url = buildHuggingFaceResolveUrlForPath(model, file); expect(url).toContain(`/${ELIZA_1_HF_REPO}/resolve/main/`); expect(url).toContain("embedding/eliza-1-embedding.gguf"); }); it("does not declare a default KV-cache override for shipped tiers", () => { // Shipped Gemma tiers stay on F16 KV by default. QJL/TBQ cache // experiments are opt-in per runtime/backend, not catalog defaults. expect(model?.runtime?.kvCache).toBeUndefined(); }); }); } });