build(deps)!: make TTS engine SDKs optional peer dependencies - #36
build(deps)!: make TTS engine SDKs optional peer dependencies#36Joilence wants to merge 10 commits into
Conversation
`argo doctor` gains an engines section listing which TTS engines resolve, and `argo init` prints a hint when none is installed. Both derive the command from the detected install mode, since project, global and npx each need different syntax. The roll-up warns rather than fails: mlx-audio needs no npm package, so an absent npm engine cannot prove voiceover is broken, and doctor's exit code gates CI for those users.
Every site that loads an engine SDK now goes through a shared wrapper that translates a missing optional package into the exact install command, and leaves every other failure untouched. Previously each adapter used a bare catch that reported any load failure as "not installed", which misdirects users whose package is present but broken. The transcriber's `@huggingface/transformers` import becomes dynamic. A top-level import there is reachable from the CLI entry, so it took down every command, including `validate` and `export`, for anyone who had not installed a 400 MB ONNX runtime. A module-not-found alone is not enough to blame the optional package: the same code surfaces when the package is present but one of its own dependencies is not. onnxruntime-node requires a per-arch native binding at runtime, so the wrapper confirms the package is genuinely absent before rewriting the error, and the CLI now prints the underlying cause. Install hints are resolved per install mode, because the correct command differs. Global trees do not hoist, so Kokoro needs both packages in one command; two separate `npm i -g` runs leave a second ONNX copy. Detection asks the resolver whether the project reaches this same copy rather than parsing paths, which keeps pnpm, nested npm, and Yarn PnP working.
Moves kokoro-js, @huggingface/transformers, openai, @elevenlabs/elevenlabs-js, @google/genai and sarvamai out of dependencies and optionalDependencies and into optional peerDependencies. optionalDependencies does not mean opt-in: npm installs those by default and only tolerates install failure. peerDependenciesMeta.optional is the one field npm never auto-installs. Measured against the published 0.38.1, a base install drops from ~920 MB to ~27 MB, ~47 MB with OpenAI, and a Kokoro user lands at ~435 MB, still less than half of what everyone paid before. Cloud SDK ranges are open-ended. An optional peer still constrains the consumer's copy, so pinning openai to ^4 made installation fail outright with ERESOLVE for anyone already on v5, v6 or v7, including people who never use that engine. openai shipped three majors in fourteen months, so an enumerated bound goes stale within months and silently reintroduces that failure, whereas an over-wide bound at worst surfaces an SDK error in one engine at generate() time. The call surface is verified identical on 4.104.0, 5.23.2, 6.49.0 and 7.4.0. @huggingface/transformers stays bounded at ^3.5.1 || ^4.2.0 so it can dedupe against kokoro-js, which requires ^3.5.1. Pinning ^4 produces a second nested copy plus a second ONNX runtime, because overrides only apply in a root package.json and stop working once Argo is a dependency. The devDependency tracks ^3.5.1 so the repo's own tree hoists one copy and CI exercises the version consumers actually resolve. BREAKING CHANGE: no TTS engine is installed by default. Users of the default Kokoro engine must run `npm i kokoro-js`. `argo doctor` and `argo init` report what is missing and the command for the detected install mode.
Covers the resolution probe directly, including the version-range-suffixed specifier form, and pins that a transitive module-not-found is not attributed to the optional package. Adds a static-import guard. Every optional SDK is a devDependency, so all six resolve during tests and nothing else in the suite can notice a regression from `await import(x)` back to a top-level import, which would break every command for users who installed no engine.
Records that no TTS engine ships by default, the per-mode install commands, and the one-command constraint for a global Kokoro install. Engine sizes are stated on a single measurement basis, with the realistic end-to-end totals alongside, since the per-package figures do not simply add up.
ReviewDesign holds up — no static import of any of the six optional packages survives in Also: 1.
|
|
Correction to my review: CI has now run and all four checks pass (Unit tests, ci-smoke on chromium/firefox/webkit). The "no checks reported" note is stale — disregard it. Worth being precise about what that does and doesn't clear, though: it does not retire finding 1. Both workflows pin Reproducing it needs a different Node, not a different test: The file dies at collection, so none of its assertions run — and it's the only thing standing between a stray static import and the whole optional-peer design. Adding Findings 2 and 4 are also invisible to CI by construction — both are about which install command gets printed to a user in a global/npx tree, which nothing exercises. |
…e-deps # Conflicts: # package-lock.json
|
Thanks for the review. 1. Fixed in Validating it turned up that 2. Left alone. Kokoro loads from its private nested copy, so reporting it installed is accurate, and checking every entry would flip that row to "not installed" for a working engine. Happy to reconsider if you have a tree I did not reproduce. 3. Fixed in One correction: 4. Fixed in the same commit, with two things beyond the finding. The hints are written 5. Fixed in You were right that 2 and 4 were invisible to CI. Found, not fixed
|
|
Reproduced all of this. Taking them in order of how wrong I was. 2 — you're right, and my finding was wrong on its premiseI assumed So npm cannot install kokoro-js without it, the nested copy always exists, and probing 1 — confirmed, and
|
Co-drafted PR with AI, self-reviewed.
Why
npm i @argo-video/cli@0.38.1installs 920 MB. Most is ONNX runtime only Kokoro needs, plus four cloud SDKs which are likely not need all of.optionalDependenciesis not opt-in: npm installs those by default and only tolerates install failure.peerDependenciesMeta.optionalis the one field npm never auto-installs.What
All six engine SDKs (
kokoro-js,@huggingface/transformers,openai,@elevenlabs/elevenlabs-js,@google/genai,sarvamai) become optional peers. Users install only what they use.Kokoro users also gain: dropping the forced transformers v4 upgrade keeps the
onnxruntime-nodethatkokoro-jsalready wanted.src/tts/transcribe.tsnow imports@huggingface/transformersdynamically. The top-level import was reachable fromsrc/cli.ts, so it broke every command includingvalidateandexportwhen the package was absent. This blocked the whole change.importOptional()wrapper. The previous barecatchreported any load failure as "not installed", misdirecting users whose package is present but whose native binding is not.@huggingface/transformersis^3.5.1 || ^4.2.0so it dedupes againstkokoro-js(^3.5.1). Pinning^4yields a second nested copy plus a second ONNX runtime, sinceoverridesonly apply in a rootpackage.json.npm ifail with ERESOLVE for anyone on a newer major, including people who never use that engine. openai shipped three majors in fourteen months. Call surface verified identical on 4.104.0, 5.23.2, 6.49.0, 7.4.0.engines.mlxAudio()is unaffected: it speaks HTTP to a local Python server, no npm package to resolve.anysurfaced two pre-existing SDK call bugs (ElevenLabsmodel_idvsmodelId; Sarvam constructs the CJS default, butsarvamaiexportsSarvamAInamed). Both need API keys to test, so this PR preserves existing runtime behaviour rather than mixing in a fix.Touches
src/cli.tsin two small hunks, overlapping open #30. Happy to rebase once that lands.What users see
Fresh install is 27 MB with no engine.
argo doctorsays exactly what is missing and what to run:argo initends with the same nudge, so new projects hit it before their first run:Reaching TTS without the package fails at the first clip, naming the command again:
Global installs get different commands, unprompted, because global trees do not hoist and two separate
npm i -gruns leave a second ONNX copy:Following that command verbatim resolves it, and lights up transcription for free:
Silent demos (no
textin the manifest) need no engine at all and keep working on the 27 MB install.demos/ci-smokeis exactly this case, so CI covers the path.Breaking change
No TTS engine installs by default. Kokoro users run
npm i kokoro-js, ornpm i -g kokoro-js @huggingface/transformers@^3for a global install.argo doctor,argo init, and the runtime error all print the correct command for the detected mode.Test
npm test: 681 pass, 60 files.npx tsx bin/argo.js pipeline ci-smoke --config demos/ci-smoke.config.mjs --browser chromiumpasses locally, producing the 10.0s mp4 CI verifies.argo doctor.argo pipelineon a silent demo with zero engines installed: 15.1s 1280x720 h264 mp4, no audio stream, overlays and click intact. Previously failed outright.npm i kokoro-jsexactly asargo doctorinstructs, thenargo pipelineon a narrated demo: 12.7s mp4, aac 24 kHz mono, mean -24.0 dB / max -3.1 dB over 303104 samples, subtitles generated.openai@^7installs cleanly, consumer onopenai@3.3.0still correctly rejected./tmpand$HOME), and a pnpm.pnpm/store layout.