// Browser-only Sherpa adapter. The Emscripten runtime is a locally packaged,
// single-threaded 1.13.4 build. Model files are mounted from CapabilityModelStore;
// neither this module nor the packaged extension contains model weights.
import { CapabilityModelStore } from "./capability-model-store.js";
export class SherpaBrowserRuntime {
    models;
    runtimeLoader;
    apiLoader;
    modulePromise;
    apiPromise;
    constructor(models = new CapabilityModelStore(), runtimeLoader = loadRuntimeFactory, apiLoader = loadApi) {
        this.models = models;
        this.runtimeLoader = runtimeLoader;
        this.apiLoader = apiLoader;
    }
    streamingFactory(manifest) {
        return async () => {
            const [module, api] = await Promise.all([this.loadModule(), this.loadApi()]);
            const root = await this.mount(manifest, module);
            return api.createOnlineRecognizer(module, onlineConfig(root));
        };
    }
    segmentedFactory(manifest) {
        return async () => {
            const [module, api] = await Promise.all([this.loadModule(), this.loadApi()]);
            const root = await this.mount(manifest, module);
            return new api.OfflineRecognizer(offlineTransducerConfig(root), module);
        };
    }
    loadModule() {
        this.modulePromise ??= this.runtimeLoader().then((factory) => factory({
            // The generated file is deliberately renamed during packaging. Do not rely
            // on Emscripten's sibling-name heuristic, which would otherwise request the
            // upstream `sherpa-onnx-wasm-main-asr.wasm` filename.
            locateFile: () => new URL("sherpa/sherpa-runtime.wasm", import.meta.url).href,
        })).then((module) => {
            if (!module.FS?.writeFile)
                throw new Error("sherpa_runtime_filesystem_unavailable");
            return module;
        });
        return this.modulePromise;
    }
    loadApi() {
        this.apiPromise ??= this.apiLoader();
        return this.apiPromise;
    }
    async mount(manifest, module) {
        if (!(await this.models.isReady(manifest)))
            throw new Error("audio_unconfigured");
        const root = `/models/${manifest.id}`;
        module.FS.mkdirTree?.(root);
        await Promise.all(manifest.files.map(async (file) => module.FS.writeFile(`${root}/${file.path}`, await this.models.fileBytes(manifest, file.path))));
        return root;
    }
}
function onlineConfig(root) {
    return {
        featConfig: { sampleRate: 16_000, featureDim: 80 },
        modelConfig: {
            transducer: { encoder: `${root}/encoder-epoch-99-avg-1.int8.onnx`, decoder: `${root}/decoder-epoch-99-avg-1.onnx`, joiner: `${root}/joiner-epoch-99-avg-1.int8.onnx` },
            paraformer: { encoder: "", decoder: "" }, zipformer2Ctc: { model: "" }, nemoCtc: { model: "" }, toneCtc: { model: "" },
            tokens: `${root}/tokens.txt`, numThreads: 1, provider: "cpu", debug: 0, modelType: "", modelingUnit: "cjkchar", bpeVocab: "",
        },
        decodingMethod: "greedy_search", maxActivePaths: 4, enableEndpoint: 1,
        rule1MinTrailingSilence: 2.4, rule2MinTrailingSilence: 0.8, rule3MinUtteranceLength: 20,
        hotwordsFile: "", hotwordsScore: 1.5, ctcFstDecoderConfig: { graph: "", maxActive: 3000 }, ruleFsts: "", ruleFars: "",
    };
}
function offlineTransducerConfig(root) {
    return {
        featConfig: { sampleRate: 16_000, featureDim: 80 },
        modelConfig: {
            transducer: { encoder: `${root}/encoder-epoch-99-avg-1.int8.onnx`, decoder: `${root}/decoder-epoch-99-avg-1.onnx`, joiner: `${root}/joiner-epoch-99-avg-1.int8.onnx` },
            tokens: `${root}/tokens.txt`, numThreads: 1, provider: "cpu", debug: 0, modelType: "", modelingUnit: "cjkchar", bpeVocab: "",
        },
        decodingMethod: "greedy_search", maxActivePaths: 4, hotwordsFile: "", hotwordsScore: 1.5, ruleFsts: "", ruleFars: "", blankPenalty: 0,
    };
}
async function loadRuntimeFactory() {
    const module = await import(new URL("sherpa/sherpa-runtime.mjs", import.meta.url).href);
    if (!module.default)
        throw new Error("sherpa_runtime_missing");
    return module.default;
}
async function loadApi() {
    return import(new URL("sherpa/sherpa-api.mjs", import.meta.url).href);
}
