Keep Parakeet on WASM unless WebGPU is chosen explicitly, and never offer it on phones

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-29 21:51:26 +01:00
1 parent 827e9a8dae
commit c5a57cd33a
4 files changed
+99 -1

No files matched your search

+31 -1
View File
@@ -1,5 +1,11 @@
import { describe, test, expect } from "bun:test";
import { isLikelyMobile, shouldWarnBeforeLoad } from "../src/lib/mobileMemoryGuard";
import {
isLikelyMobile,
isModelAllowedOnDevice,
modelsForDevice,
shouldWarnBeforeLoad,
} from "../src/lib/mobileMemoryGuard";
import { MODELS, PARAKEET_MODEL_ID } from "../src/lib/models";
// Pure UA/heuristic logic (D-027) — no browser, no navigator.
@@ -99,3 +105,27 @@ describe("shouldWarnBeforeLoad", () => {
).toBe(false);
});
});
describe("desktop-only models (D-WS7a)", () => {
const parakeet = MODELS.find((model) => model.id === PARAKEET_MODEL_ID)!;
const phone = { userAgent: ANDROID_UA, maxTouchPoints: 5, deviceMemoryGB: 8 };
const ipad = { userAgent: IPAD_DESKTOP_UA, maxTouchPoints: 5, deviceMemoryGB: undefined };
const desktop = { userAgent: DESKTOP_WINDOWS_UA, maxTouchPoints: 0, deviceMemoryGB: 8 };
test("Parakeet is never offered on phones or tablets, even high-memory ones", () => {
expect(isModelAllowedOnDevice(parakeet, phone)).toBe(false);
expect(isModelAllowedOnDevice(parakeet, ipad)).toBe(false);
expect(isModelAllowedOnDevice(parakeet, desktop)).toBe(true);
});
test("Whisper models stay allowed everywhere (they get the D-027 confirm instead)", () => {
for (const model of MODELS.filter((m) => m.id !== PARAKEET_MODEL_ID)) {
expect(isModelAllowedOnDevice(model, phone)).toBe(true);
}
});
test("modelsForDevice filters the list, keeping order", () => {
expect(modelsForDevice(MODELS, phone)).toEqual(MODELS.filter((m) => m !== parakeet));
expect(modelsForDevice(MODELS, desktop)).toEqual([...MODELS]);
});
});
+24
View File
@@ -2,6 +2,7 @@ import { describe, test, expect } from "bun:test";
import {
applyLoadProgress,
deviceAttempts,
parakeetDeviceAttempts,
dtypeRequiresF16,
initialLoadProgress,
isUiToWorkerMessage,
@@ -224,6 +225,29 @@ describe("deviceAttempts (D-004, D-017)", () => {
});
});
describe("parakeetDeviceAttempts (D-WS7a)", () => {
const everything = { webnn: true, webgpu: true, webgpuF16: true };
test("auto never picks an accelerator for Parakeet", () => {
expect(parakeetDeviceAttempts("auto", everything)).toEqual(["wasm"]);
});
test("explicit WebGPU is tried (then WASM) only with shader-f16", () => {
expect(parakeetDeviceAttempts("webgpu", everything)).toEqual(["webgpu", "wasm"]);
expect(parakeetDeviceAttempts("webgpu", { ...everything, webgpuF16: false })).toEqual([
"wasm",
]);
expect(parakeetDeviceAttempts("webgpu", { ...everything, webgpu: false })).toEqual([
"wasm",
]);
});
test("WebNN and WASM preferences run WASM", () => {
expect(parakeetDeviceAttempts("webnn", everything)).toEqual(["wasm"]);
expect(parakeetDeviceAttempts("wasm", everything)).toEqual(["wasm"]);
});
});
describe("TranscribeProgressTracker", () => {
// Production shape: 30 s windows advancing by 20 s (30 − 2·5, the worker's
// chunk/stride settings), like the chunked ASR pipeline.