fix(calls): make ML denoise build-honest + gate desktop trigger on CI
Audit/repair of the multi-model denoise work so it actually builds and only exposes working, self-hosted models. - Complete the DTLN/DFN3 revert: uninstall @workadventure/noise-suppression and deepfilternet3-noise-filter (package.json + lockfile), drop the unused DTLN asset-copy block from vite.config.js (was shipping ~2MB of unused tflite/wasm), and narrow DenoiseModelId to the bundled models (rnnoise, speex). Coerce any retired persisted model value back to the default. - Fix General.tsx CI typecheck failures introduced by the denoise UI: restore three imports the rewrite deleted (useDateFormatItems, SequenceCardStyle, useTauriUpdater), add the missing denoise/sound imports, and correct hallucinated Folds props (Text has no variant/bold; Box uses alignItems/justifyContent). tsc now passes with 0 errors. - Harden the vite denoise plugin: required RNNoise/Speex/gate assets and the shim now fail the build loudly if missing (instead of a silent warn that shipped a broken ML feature), and the index.html shim injection is verified. - CI: move the cinny-desktop submodule bump into ci.yml as a `trigger-desktop` job gated on `needs: build`, and delete the standalone trigger-desktop.yml. A failing push no longer kicks off the slow Tauri builds in parallel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+26
-34
@@ -80,6 +80,10 @@ function lotusDenoise() {
|
||||
fs.mkdirSync(denoiseDir, { recursive: true });
|
||||
|
||||
const sapphi = path.resolve('node_modules/@sapphi-red/web-noise-suppressor/dist');
|
||||
// All bundled denoise assets are REQUIRED: every entry backs a model the
|
||||
// UI can select (RNNoise, Speex) or the optional noise gate. A missing
|
||||
// source means a partial/changed install would otherwise silently ship a
|
||||
// broken ML feature (worklet 404 -> raw mic), so we fail the build instead.
|
||||
const assets = [
|
||||
[
|
||||
path.join(sapphi, 'rnnoise/workletProcessor.js'),
|
||||
@@ -87,49 +91,31 @@ function lotusDenoise() {
|
||||
],
|
||||
[path.join(sapphi, 'rnnoise.wasm'), path.join(denoiseDir, 'rnnoise.wasm')],
|
||||
[path.join(sapphi, 'rnnoise_simd.wasm'), path.join(denoiseDir, 'rnnoise_simd.wasm')],
|
||||
[
|
||||
path.join(sapphi, 'speex/workletProcessor.js'),
|
||||
path.join(denoiseDir, 'speexWorklet.js'),
|
||||
],
|
||||
[path.join(sapphi, 'speex/workletProcessor.js'), path.join(denoiseDir, 'speexWorklet.js')],
|
||||
[path.join(sapphi, 'speex.wasm'), path.join(denoiseDir, 'speex.wasm')],
|
||||
[
|
||||
path.join(sapphi, 'noiseGate/workletProcessor.js'),
|
||||
path.join(denoiseDir, 'noiseGateWorklet.js'),
|
||||
],
|
||||
// DTLN (WorkAdventure v0.0.4)
|
||||
[
|
||||
path.resolve('node_modules/@workadventure/noise-suppression/dist/audio-worklet.js'),
|
||||
path.join(denoiseDir, 'dtlnWorklet.js'),
|
||||
],
|
||||
[
|
||||
path.resolve('node_modules/@workadventure/noise-suppression/dist/assets/audio-worklet-processor.js'),
|
||||
path.join(denoiseDir, 'dtlnProcessor.js'),
|
||||
],
|
||||
[
|
||||
path.resolve('node_modules/@workadventure/noise-suppression/dist/vendor/litert/litert_wasm_internal.wasm'),
|
||||
path.join(denoiseDir, 'litert_wasm_internal.wasm'),
|
||||
],
|
||||
[
|
||||
path.resolve('node_modules/@workadventure/noise-suppression/dist/assets/model_quant_1.tflite'),
|
||||
path.join(denoiseDir, 'model_1.tflite'),
|
||||
],
|
||||
[
|
||||
path.resolve('node_modules/@workadventure/noise-suppression/dist/assets/model_quant_2.tflite'),
|
||||
path.join(denoiseDir, 'model_2.tflite'),
|
||||
],
|
||||
];
|
||||
assets.forEach(([s, d]) => {
|
||||
if (fs.existsSync(s)) {
|
||||
fs.copyFileSync(s, d);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`[lotus-denoise] Asset missing, will be populated by CI: ${s}`);
|
||||
}
|
||||
});
|
||||
const missing = assets.filter(([s]) => !fs.existsSync(s)).map(([s]) => s);
|
||||
if (missing.length > 0) {
|
||||
throw new Error(
|
||||
`[lotus-denoise] Required denoise asset(s) missing — build aborted to avoid shipping a broken ML feature:\n ${missing.join('\n ')}`,
|
||||
);
|
||||
}
|
||||
assets.forEach(([s, d]) => fs.copyFileSync(s, d));
|
||||
|
||||
const shimSrc = path.resolve('build/lotus-denoise.js');
|
||||
if (fs.existsSync(shimSrc)) fs.copyFileSync(shimSrc, path.join(ecDir, 'lotus-denoise.js'));
|
||||
if (!fs.existsSync(shimSrc)) {
|
||||
throw new Error(`[lotus-denoise] Missing shim source ${shimSrc} — build aborted.`);
|
||||
}
|
||||
fs.copyFileSync(shimSrc, path.join(ecDir, 'lotus-denoise.js'));
|
||||
|
||||
// Inject the shim <script> into Element Call's index.html so it runs
|
||||
// before EC captures the mic. Verify the injection actually landed —
|
||||
// if EC's bundle ever drops its deferred module entry the replace would
|
||||
// no-op and ML would silently never engage, so fail loudly.
|
||||
const indexPath = path.join(ecDir, 'index.html');
|
||||
if (fs.existsSync(indexPath)) {
|
||||
let html = fs.readFileSync(indexPath, 'utf8');
|
||||
@@ -139,6 +125,12 @@ function lotusDenoise() {
|
||||
/<script type="module"/,
|
||||
'<script src="./lotus-denoise.js"></script><script type="module"',
|
||||
);
|
||||
if (!html.includes('lotus-denoise.js')) {
|
||||
throw new Error(
|
||||
'[lotus-denoise] Failed to inject shim into Element Call index.html ' +
|
||||
'(no `<script type="module">` entry found) — build aborted.',
|
||||
);
|
||||
}
|
||||
fs.writeFileSync(indexPath, html);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user