From 1393397e5820d2ddebbce945f7aae2bc3c33477a Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:00:03 +0200 Subject: [PATCH 1/9] refactor(tts): load optional SDKs through importOptional 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. --- src/cli.ts | 17 ++- src/music/musicgen.ts | 17 +-- src/optional-deps.ts | 217 ++++++++++++++++++++++++++++++++ src/tts/engines/elevenlabs.ts | 17 ++- src/tts/engines/gemini.ts | 14 +-- src/tts/engines/kokoro.ts | 11 +- src/tts/engines/openai.ts | 14 +-- src/tts/engines/sarvam.ts | 17 ++- src/tts/engines/transformers.ts | 19 +-- src/tts/transcribe.ts | 18 ++- 10 files changed, 298 insertions(+), 63 deletions(-) create mode 100644 src/optional-deps.ts diff --git a/src/cli.ts b/src/cli.ts index aed678d..49e735b 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -40,6 +40,14 @@ function validateDemoName(name: string): string { return name; } +/** Default to Kokoro when the config names no engine. + * + * Kokoro is an optional peer dependency, but do not probe for it here. + * Constructing the engine loads nothing, and TTS is the first step of the + * pipeline, so `importOptional` raises the same install hint at the first + * `generate()` a moment later. Probing up front instead breaks the demos + * that need no engine at all: silent demos carry no `text`, so + * `generateClips` filters every scene out and never calls `generate()`. */ async function ensureTTSEngine(config: ArgoConfig): Promise { if (!config.tts.engine) { const { KokoroEngine } = await import('./tts/kokoro.js'); @@ -554,5 +562,12 @@ export function createProgram(): Command { } if (process.env.VITEST === undefined) { - createProgram().parseAsync(process.argv).catch((err) => { console.error(err.message); process.exit(1); }); + createProgram().parseAsync(process.argv).catch((err) => { + console.error(err.message); + // Optional-dependency errors wrap the original resolution failure. Without + // this, the underlying cause is unreachable from every CLI path. + if (err?.cause instanceof Error) console.error(` caused by: ${err.cause.message}`); + if (process.env.DEBUG) console.error(err.stack); + process.exit(1); + }); } diff --git a/src/music/musicgen.ts b/src/music/musicgen.ts index 7f35678..e59c9eb 100644 --- a/src/music/musicgen.ts +++ b/src/music/musicgen.ts @@ -4,6 +4,7 @@ */ import crypto from 'node:crypto'; +import { importOptional, MUSICGEN_DEP } from '../optional-deps.js'; import fs from 'node:fs'; import path from 'node:path'; import { createWavBuffer } from '../tts/engine.js'; @@ -76,18 +77,10 @@ export async function generateMusic(options: MusicGenOptions): Promise { const maxNewTokens = Math.ceil(durationSec * TOKENS_PER_SECOND); // Lazy-load transformers (same pattern as TTS Transformers engine) - let AutoTokenizer: any; - let MusicgenForConditionalGeneration: any; - try { - ({ AutoTokenizer, MusicgenForConditionalGeneration } = await import( - '@huggingface/transformers' - )); - } catch { - throw new Error( - "MusicGen requires the '@huggingface/transformers' package. " + - 'Install it with: npm i @huggingface/transformers', - ); - } + const { AutoTokenizer, MusicgenForConditionalGeneration }: any = await importOptional( + () => import('@huggingface/transformers'), + MUSICGEN_DEP, + ); console.log(` \u25b8 Loading model: ${MODEL_ID}`); console.log( diff --git a/src/optional-deps.ts b/src/optional-deps.ts new file mode 100644 index 0000000..785b0aa --- /dev/null +++ b/src/optional-deps.ts @@ -0,0 +1,217 @@ +/** + * Optional engine dependencies: detection and actionable install hints. + * + * Argo's TTS engines and the Whisper transcriber are optional peer + * dependencies. npm does not install them automatically, so the package + * stays small for anyone who only uses one engine. When a code path needs + * a package that isn't there, the error has to say exactly what to run. + * + * The correct command differs by how Argo itself was installed: + * + * - project (`npm i -D @argo-video/cli`): npm hoists the engine's own + * transitive deps to the project root, where Argo can resolve them. + * - global (`npm i -g`): each global install is its own tree with no + * hoisting between them. `npm i -g kokoro-js` alone leaves + * `@huggingface/transformers` nested privately under `kokoro-js/`, where + * Argo cannot see it, so the global hint names both packages. They must + * go in ONE command: two separate `npm i -g` runs produce two copies of + * onnxruntime (~840MB vs ~410MB). + * - npx: the throwaway tree holds only what `--package` put in it. + */ +import { createRequire } from 'node:module'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { dirname, join, sep } from 'node:path'; + +export type InstallMode = 'project' | 'global' | 'npx'; + +const PKG_NAME = '@argo-video/cli'; + +/** `kokoro-js@^1.2.1` -> `kokoro-js`. Install lists carry version ranges for + * the user to paste; resolution and error text want the bare name. */ +function bareName(specifier: string): string { + return specifier.replace(/@\^?[\d.].*$/, ''); +} + +/** Resolve a bare specifier as if from `dir`, or null if it does not resolve. + * + * Uses `createRequire` rather than `import.meta.resolve`: the latter is + * undefined on Node before 18.19/20.6 and under vite-node's SSR transform, + * where an optional-chained call silently succeeds and every probe answers + * "installed". `createRequire().resolve` exists everywhere and throws. */ +function resolveFrom(dir: string, specifier: string): string | null { + try { + return createRequire(pathToFileURL(join(dir, 'noop.js'))).resolve(specifier); + } catch (err) { + if (isModuleNotFound(err)) return null; + throw err; + } +} + +/** Packages to install for one optional capability, per install mode. + * `global` is a separate list because global trees do not hoist. */ +export interface OptionalDepSpec { + /** Human-readable capability name, used in the error message. */ + feature: string; + /** Install list for a project-local Argo. */ + project: string[]; + /** Install list for a globally installed Argo. */ + global: string[]; +} + +export const KOKORO_DEP: OptionalDepSpec = { + feature: 'Kokoro local TTS', + project: ['kokoro-js'], + // kokoro-js keeps its own transformers copy private in a global tree. + global: ['kokoro-js', '@huggingface/transformers@^3'], +}; + +export const TRANSFORMERS_DEP: OptionalDepSpec = { + feature: 'local Transformers.js models', + project: ['@huggingface/transformers'], + global: ['@huggingface/transformers'], +}; + +export const WHISPER_DEP: OptionalDepSpec = { + feature: 'Whisper word-level transcription (`tts.transcribe`)', + project: ['@huggingface/transformers'], + global: ['@huggingface/transformers'], +}; + +export const MUSICGEN_DEP: OptionalDepSpec = { + feature: 'MusicGen background music generation', + project: ['@huggingface/transformers'], + global: ['@huggingface/transformers'], +}; + +export const OPENAI_DEP: OptionalDepSpec = { + feature: 'OpenAI TTS', + project: ['openai'], + global: ['openai'], +}; + +export const ELEVENLABS_DEP: OptionalDepSpec = { + feature: 'ElevenLabs TTS', + project: ['@elevenlabs/elevenlabs-js'], + global: ['@elevenlabs/elevenlabs-js'], +}; + +export const GEMINI_DEP: OptionalDepSpec = { + feature: 'Gemini TTS', + project: ['@google/genai'], + global: ['@google/genai'], +}; + +export const SARVAM_DEP: OptionalDepSpec = { + feature: 'Sarvam TTS', + project: ['sarvamai'], + global: ['sarvamai'], +}; + +let cachedMode: InstallMode | null = null; + +/** Where is this copy of Argo installed from? Cached per process. + * + * npx unpacks into `~/.npm/_npx//`, which is unambiguous. Otherwise + * ask the real resolver: does the user's project resolve `@argo-video/cli` + * to the very copy now running? If so, `npm i ` lands somewhere + * this process can see it, which is what makes the hint correct. + * + * Delegating to the resolver rather than parsing the path keeps pnpm's + * `.pnpm//node_modules/...` store, npm's nested fallback layout, and + * Yarn PnP working without special cases. Comparing identity rather than + * mere resolvability also catches running a global Argo from inside a + * project that happens to have its own copy. */ +export function detectInstallMode(): InstallMode { + if (cachedMode) return cachedMode; + let selfDir: string; + try { + selfDir = dirname(fileURLToPath(import.meta.url)); + } catch { + // Bundled or otherwise non-file URL. Assume the common case. + cachedMode = 'project'; + return cachedMode; + } + if (selfDir.includes(`${sep}_npx${sep}`)) { + cachedMode = 'npx'; + return cachedMode; + } + const selfEntry = resolveFrom(selfDir, PKG_NAME); + if (selfEntry === null) { + // Running from a source checkout, not from an installed tree. + cachedMode = 'project'; + return cachedMode; + } + cachedMode = resolveFrom(process.cwd(), PKG_NAME) === selfEntry ? 'project' : 'global'; + return cachedMode; +} + +/** Reset the cached mode. Tests only. */ +export function resetInstallModeCache(): void { + cachedMode = null; +} + +/** The exact command to install `spec` for the current install mode. */ +export function installCommand(spec: OptionalDepSpec, mode = detectInstallMode()): string { + switch (mode) { + case 'global': + // One command, not several: separate global installs do not dedupe. + return `npm i -g ${spec.global.join(' ')}`; + case 'npx': { + const pkgs = [PKG_NAME, ...spec.global].map((p) => `-p ${p}`).join(' '); + return `npx ${pkgs} -- argo `; + } + case 'project': + return `npm i ${spec.project.join(' ')}`; + } +} + +/** True when `err` is Node's "package is not installed" failure. + * + * Distinguishes a missing optional dependency from a real fault inside a + * dependency that *is* installed. Those must keep propagating unchanged. */ +export function isModuleNotFound(err: unknown): boolean { + const code = (err as { code?: string } | null)?.code; + return code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND'; +} + +/** Error explaining which optional package is missing and how to install it. */ +export function missingDependencyError(spec: OptionalDepSpec, cause?: unknown): Error { + const names = spec.project.map(bareName); + const list = names.length === 1 ? `'${names[0]}'` : names.map((n) => `'${n}'`).join(' and '); + const err = new Error( + `${spec.feature} requires ${list}, which is an optional dependency and is not installed.\n` + + ` Install it with: ${installCommand(spec)}`, + ); + if (cause !== undefined) (err as Error & { cause?: unknown }).cause = cause; + return err; +} + +/** Dynamic-import wrapper that turns a missing optional package into an + * actionable error, and leaves every other failure untouched. + * + * A module-not-found is not enough on its own to blame the optional + * package: the same code surfaces when the package is present but one of + * *its* dependencies fails to load. `onnxruntime-node` does exactly that, + * requiring a per-arch native binding at runtime, so a machine without a + * matching prebuilt binary would otherwise be told to install `kokoro-js` + * when it already has it. Confirm the package really is absent first. */ +export async function importOptional(load: () => Promise, spec: OptionalDepSpec): Promise { + try { + return await load(); + } catch (err) { + if (isModuleNotFound(err) && !isDepInstalled(spec)) { + throw missingDependencyError(spec, err); + } + throw err; + } +} + +/** Is the optional package for `spec` resolvable right now? Used by + * `argo doctor` to report engine availability without loading anything. + * + * Only a genuine module-not-found means "absent". A corrupt manifest or a + * broken `exports` map throws a different code and must not be reported as + * "not installed", or the user reinstalls a package that is already there. */ +export function isDepInstalled(spec: OptionalDepSpec): boolean { + return resolveFrom(dirname(fileURLToPath(import.meta.url)), bareName(spec.project[0])) !== null; +} diff --git a/src/tts/engines/elevenlabs.ts b/src/tts/engines/elevenlabs.ts index c4f36c1..24a4e46 100644 --- a/src/tts/engines/elevenlabs.ts +++ b/src/tts/engines/elevenlabs.ts @@ -1,4 +1,5 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; +import { importOptional, ELEVENLABS_DEP } from '../../optional-deps.js'; export interface ElevenLabsEngineOptions { apiKey?: string; @@ -39,15 +40,13 @@ export class ElevenLabsEngine implements TTSEngine { async generate(text: string, options: TTSEngineOptions): Promise { if (!text?.trim()) throw new Error('TTS text must not be empty'); - let ElevenLabsClient: any; - try { - // @ts-ignore — @elevenlabs/elevenlabs-js is an optional dependency - ({ ElevenLabsClient } = await import('@elevenlabs/elevenlabs-js')); - } catch { - throw new Error( - "ElevenLabs TTS engine requires the '@elevenlabs/elevenlabs-js' package. Install it with: npm i @elevenlabs/elevenlabs-js" - ); - } + // Loosely typed on purpose: the `convert()` call below uses snake_case + // keys that the current SDK typings do not accept. Typing it would change + // request shape, which is a behavioural fix, not a packaging one. + const { ElevenLabsClient }: any = await importOptional( + () => import('@elevenlabs/elevenlabs-js'), + ELEVENLABS_DEP, + ); const client = new ElevenLabsClient({ apiKey: this.resolveApiKey() }); const audioStream = await client.textToSpeech.convert( diff --git a/src/tts/engines/gemini.ts b/src/tts/engines/gemini.ts index 730835a..08f17ef 100644 --- a/src/tts/engines/gemini.ts +++ b/src/tts/engines/gemini.ts @@ -1,4 +1,5 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; +import { importOptional, GEMINI_DEP } from '../../optional-deps.js'; export interface GeminiEngineOptions { apiKey?: string; @@ -33,15 +34,10 @@ export class GeminiEngine implements TTSEngine { async generate(text: string, options: TTSEngineOptions): Promise { if (!text?.trim()) throw new Error('TTS text must not be empty'); - let GoogleGenAI: any; - try { - // @ts-ignore — @google/genai is an optional dependency - ({ GoogleGenAI } = await import('@google/genai')); - } catch { - throw new Error( - "Gemini TTS engine requires the '@google/genai' package. Install it with: npm i @google/genai" - ); - } + const { GoogleGenAI } = await importOptional( + () => import('@google/genai'), + GEMINI_DEP, + ); const ai = new GoogleGenAI({ apiKey: this.resolveApiKey() }); const response = await ai.models.generateContent({ diff --git a/src/tts/engines/kokoro.ts b/src/tts/engines/kokoro.ts index 161f0dd..71c46f6 100644 --- a/src/tts/engines/kokoro.ts +++ b/src/tts/engines/kokoro.ts @@ -1,5 +1,6 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; import { splitTextForTTS, concatSamples } from '../engine.js'; +import { importOptional, KOKORO_DEP } from '../../optional-deps.js'; export interface KokoroEngineOptions { modelId?: string; @@ -31,8 +32,16 @@ export class KokoroEngine implements TTSEngine { if (this.tts) return this.tts; if (!this.initPromise) { this.initPromise = (async () => { + // Resolve the package first so a missing optional dependency reports + // the install command instead of being reported as a failed download. + const { KokoroTTS } = await importOptional( + () => import('kokoro-js'), + KOKORO_DEP, + ).catch((err) => { + this.initPromise = null; + throw err; + }); try { - const { KokoroTTS } = await import('kokoro-js'); this.tts = await KokoroTTS.from_pretrained(this.modelId, { dtype: this.dtype as 'fp32' | 'fp16' | 'q8' | 'q4' | 'q4f16', device: this.device, diff --git a/src/tts/engines/openai.ts b/src/tts/engines/openai.ts index 1b48b0c..2b5d70f 100644 --- a/src/tts/engines/openai.ts +++ b/src/tts/engines/openai.ts @@ -1,4 +1,5 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; +import { importOptional, OPENAI_DEP } from '../../optional-deps.js'; export interface OpenAIEngineOptions { apiKey?: string; @@ -39,15 +40,10 @@ export class OpenAIEngine implements TTSEngine { async generate(text: string, options: TTSEngineOptions): Promise { if (!text?.trim()) throw new Error('TTS text must not be empty'); - let OpenAI: any; - try { - // @ts-ignore — openai is an optional dependency - ({ OpenAI } = await import('openai')); - } catch { - throw new Error( - "OpenAI TTS engine requires the 'openai' package. Install it with: npm i openai" - ); - } + const { OpenAI } = await importOptional( + () => import('openai'), + OPENAI_DEP, + ); const client = new OpenAI({ apiKey: this.resolveApiKey() }); diff --git a/src/tts/engines/sarvam.ts b/src/tts/engines/sarvam.ts index 0e8f1d1..ecbe986 100644 --- a/src/tts/engines/sarvam.ts +++ b/src/tts/engines/sarvam.ts @@ -1,4 +1,5 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; +import { importOptional, SARVAM_DEP } from '../../optional-deps.js'; export interface SarvamEngineOptions { apiKey?: string; @@ -33,15 +34,13 @@ export class SarvamEngine implements TTSEngine { async generate(text: string, options: TTSEngineOptions): Promise { if (!text?.trim()) throw new Error('TTS text must not be empty'); - let SarvamAI: any; - try { - // @ts-ignore — sarvamai is an optional dependency - ({ default: SarvamAI } = await import('sarvamai')); - } catch { - throw new Error( - "Sarvam TTS engine requires the 'sarvamai' package. Install it with: npm i sarvamai" - ); - } + // Loosely typed on purpose: preserves the existing `default` interop + // shape. See the packaging PR notes about `sarvamai` also exporting a + // named `SarvamAI`, which is a separate behavioural question. + const { default: SarvamAI }: any = await importOptional( + () => import('sarvamai'), + SARVAM_DEP, + ); const client = new SarvamAI({ apiSubscriptionKey: this.resolveApiKey() }); const response = await client.textToSpeech.convert({ diff --git a/src/tts/engines/transformers.ts b/src/tts/engines/transformers.ts index 3038bdf..37e524e 100644 --- a/src/tts/engines/transformers.ts +++ b/src/tts/engines/transformers.ts @@ -1,5 +1,6 @@ import type { TTSEngine, TTSEngineOptions, TTSEngineMetadata } from '../engine.js'; import { splitTextForTTS, concatSamples } from '../engine.js'; +import { importOptional, TRANSFORMERS_DEP } from '../../optional-deps.js'; export interface TransformersEngineOptions { /** Model ID from Hugging Face Hub. Default: 'onnx-community/Supertonic-TTS-ONNX' */ @@ -43,15 +44,15 @@ export class TransformersEngine implements TTSEngine { if (this.pipeline) return this.pipeline; if (!this.initPromise) { this.initPromise = (async () => { - let pipeline: any; - try { - ({ pipeline } = await import('@huggingface/transformers')); - } catch { - throw new Error( - "Transformers TTS engine requires the '@huggingface/transformers' package. " + - 'Install it with: npm i @huggingface/transformers', - ); - } + // `pipeline` stays loosely typed: dtype/device are user-supplied + // strings, and the SDK types them as closed literal unions. + const { pipeline }: any = await importOptional( + () => import('@huggingface/transformers'), + TRANSFORMERS_DEP, + ).catch((err) => { + this.initPromise = null; + throw err; + }); try { this.pipeline = await pipeline('text-to-speech', this.model, { dtype: this.dtype, diff --git a/src/tts/transcribe.ts b/src/tts/transcribe.ts index 5029b44..a7024e4 100644 --- a/src/tts/transcribe.ts +++ b/src/tts/transcribe.ts @@ -7,12 +7,18 @@ * the source of truth is the rendered audio itself — transcribe it * back with Whisper and read the per-word timestamps. * - * Uses `@huggingface/transformers` (already in tree for Kokoro). Whisper - * runs locally via ONNX, no cloud round-trip. The pipeline instance is - * cached per process so repeated calls reuse the loaded model. + * Uses `@huggingface/transformers`. Whisper runs locally via ONNX, no cloud + * round-trip. The pipeline instance is cached per process so repeated calls + * reuse the loaded model. + * + * The import is dynamic and lives inside `getTranscriber()` on purpose. + * `@huggingface/transformers` is an optional peer dependency that pulls + * ~400MB of ONNX runtime, and transcription is opt-in (`tts.transcribe`). + * A top-level import would make every Argo command, including `validate` + * and `export`, fail to even load when the package is absent. */ -import { pipeline } from '@huggingface/transformers'; import { spawnSync } from 'node:child_process'; +import { importOptional, WHISPER_DEP } from '../optional-deps.js'; export interface WordTiming { /** The word as Whisper transcribed it. Whisper emits leading spaces on @@ -53,6 +59,10 @@ let cached: { model: string; transcriber: Transcriber } | null = null; * Switching model busts the cache (rare). */ async function getTranscriber(model: string): Promise { if (cached?.model === model) return cached.transcriber; + const { pipeline } = await importOptional( + () => import('@huggingface/transformers'), + WHISPER_DEP, + ); const transcriber = (await pipeline('automatic-speech-recognition', model)) as unknown as Transcriber; cached = { model, transcriber }; return transcriber; From f9056765978e534de77ae3abbb1d31572796f00f Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:00:18 +0200 Subject: [PATCH 2/9] build(deps)!: make engine SDKs optional peer dependencies 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. --- package-lock.json | 1118 ++++++++++++++++++++++++++++----------------- package.json | 47 +- 2 files changed, 725 insertions(+), 440 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10a429a..0258f0d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,38 +9,62 @@ "version": "0.38.1", "license": "MIT", "dependencies": { - "@huggingface/transformers": "^4.2.0", "commander": "^12.0.0", - "gsap": "^3.15.0", - "kokoro-js": "^1.2.1" + "gsap": "^3.15.0" }, "bin": { "argo": "bin/argo.js" }, "devDependencies": { + "@elevenlabs/elevenlabs-js": "^2.63.0", + "@google/genai": "^1.52.0", + "@huggingface/transformers": "^3.5.1", "@playwright/test": "^1.59.1", "@types/node": "^25.5.0", + "kokoro-js": "^1.2.1", + "openai": "^4.104.0", "playwright": "^1.59.1", + "sarvamai": "^1.1.8", "typescript": "^5.5.0", "vitest": "^3.2.6" }, - "optionalDependencies": { - "@elevenlabs/elevenlabs-js": "^2.0.0", - "@google/genai": "^1.0.0", - "openai": "^4.0.0", - "sarvamai": "^1.0.0" - }, "peerDependencies": { + "@elevenlabs/elevenlabs-js": ">=2", + "@google/genai": ">=1", + "@huggingface/transformers": "^3.5.1 || ^4.2.0", "@playwright/test": ">=1.59.0", - "playwright": ">=1.59.0" + "kokoro-js": "^1.2.1", + "openai": ">=4", + "playwright": ">=1.59.0", + "sarvamai": ">=1" + }, + "peerDependenciesMeta": { + "@elevenlabs/elevenlabs-js": { + "optional": true + }, + "@google/genai": { + "optional": true + }, + "@huggingface/transformers": { + "optional": true + }, + "kokoro-js": { + "optional": true + }, + "openai": { + "optional": true + }, + "sarvamai": { + "optional": true + } } }, "node_modules/@elevenlabs/elevenlabs-js": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@elevenlabs/elevenlabs-js/-/elevenlabs-js-2.39.0.tgz", - "integrity": "sha512-Yfh2wa5Y7wwoEHi2Na1YWrkc3z21oeHMo8qhGc5kcbQoWfgQfIxWuGfXHZSmUXOJz0mNL5bAfp3hHaJEX68DIA==", + "version": "2.63.0", + "resolved": "https://registry.npmjs.org/@elevenlabs/elevenlabs-js/-/elevenlabs-js-2.63.0.tgz", + "integrity": "sha512-XiSH/KazQDlklTLQaOO9J9WFuJqFcr/wSc04lPxzEvMzLmXwfpBhlCXJ+BCmgLRCRmIpHts+IIUegAPEggH24g==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "command-exists": "^1.2.9", "node-fetch": "^2.7.0", @@ -51,9 +75,10 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz", - "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -61,9 +86,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -78,9 +103,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -95,9 +120,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -112,9 +137,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -129,9 +154,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -146,9 +171,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -163,9 +188,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -180,9 +205,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -197,9 +222,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -214,9 +239,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -231,9 +256,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -248,9 +273,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -265,9 +290,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -282,9 +307,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -299,9 +324,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -316,9 +341,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -333,9 +358,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -350,9 +375,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -367,9 +392,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -384,9 +409,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -401,9 +426,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -418,9 +443,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -435,9 +460,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -452,9 +477,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -469,9 +494,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -486,9 +511,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -503,11 +528,12 @@ } }, "node_modules/@google/genai": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.45.0.tgz", - "integrity": "sha512-+sNRWhKiRibVgc4OKi7aBJJ0A7RcoVD8tGG+eFkqxAWRjASDW+ktS9lLwTDnAxZICzCVoeAdu8dYLJVTX60N9w==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz", + "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==", + "dev": true, + "hasInstallScript": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", @@ -527,37 +553,33 @@ } }, "node_modules/@huggingface/jinja": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.6.tgz", - "integrity": "sha512-MyMWyLnjqo+KRJYSH7oWNbsOn5onuIvfXYPcc0WOGxU0eHUV7oAYUoQTl2BMdu7ml+ea/bu11UM+EshbeHwtIA==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.9.tgz", + "integrity": "sha512-uWTG+l3VJRsl7EXxYizuL3P+cCPoc3cRqbWWRcQN0FhejRfbdq0RNhCmbY/YDtnTcz9icdLYuLDjsnz4d8JMuw==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, - "node_modules/@huggingface/tokenizers": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@huggingface/tokenizers/-/tokenizers-0.1.3.tgz", - "integrity": "sha512-8rF/RRT10u+kn7YuUbUg0OF30K8rjTc78aHpxT+qJ1uWSqxT1MHi8+9ltwYfkFYJzT/oS+qw3JVfHtNMGAdqyA==", - "license": "Apache-2.0" - }, "node_modules/@huggingface/transformers": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-4.2.0.tgz", - "integrity": "sha512-8BRCoBMH0XsWaEIamuR0LrJGAfftgHAfb2Vrffy0VKlSAE/MnUJ5/h/zTfEP3fDIft+nk7TqB8xXEyABGitBjQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.8.1.tgz", + "integrity": "sha512-tsTk4zVjImqdqjS8/AOZg2yNLd1z9S5v+7oUPpXaasDRwEDhB+xnglK1k5cad26lL5/ZIaeREgWWy0bs9y9pPA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@huggingface/jinja": "^0.5.6", - "@huggingface/tokenizers": "^0.1.3", - "onnxruntime-node": "1.24.3", - "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c", - "sharp": "^0.34.5" + "@huggingface/jinja": "^0.5.3", + "onnxruntime-node": "1.21.0", + "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", + "sharp": "^0.34.1" } }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -570,6 +592,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -592,6 +615,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -614,6 +638,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -630,6 +655,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -646,6 +672,10 @@ "cpu": [ "arm" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -662,6 +692,10 @@ "cpu": [ "arm64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -678,6 +712,10 @@ "cpu": [ "ppc64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -694,6 +732,10 @@ "cpu": [ "riscv64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -710,6 +752,10 @@ "cpu": [ "s390x" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -726,6 +772,10 @@ "cpu": [ "x64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -742,6 +792,10 @@ "cpu": [ "arm64" ], + "dev": true, + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -758,6 +812,10 @@ "cpu": [ "x64" ], + "dev": true, + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -774,6 +832,10 @@ "cpu": [ "arm" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -796,6 +858,10 @@ "cpu": [ "arm64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -818,6 +884,10 @@ "cpu": [ "ppc64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -840,6 +910,10 @@ "cpu": [ "riscv64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -862,6 +936,10 @@ "cpu": [ "s390x" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -884,6 +962,10 @@ "cpu": [ "x64" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -906,6 +988,10 @@ "cpu": [ "arm64" ], + "dev": true, + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -928,6 +1014,10 @@ "cpu": [ "x64" ], + "dev": true, + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ @@ -950,6 +1040,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -969,6 +1060,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -988,6 +1080,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1007,6 +1100,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1019,6 +1113,19 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1026,50 +1133,75 @@ "dev": true, "license": "MIT" }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, "node_modules/@playwright/test": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", - "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.59.1" + "playwright": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1" @@ -1079,30 +1211,34 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", - "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", - "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", "cpu": [ "arm" ], @@ -1114,9 +1250,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", - "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", "cpu": [ "arm64" ], @@ -1128,9 +1264,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", - "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", "cpu": [ "arm64" ], @@ -1142,9 +1278,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", - "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", "cpu": [ "x64" ], @@ -1156,9 +1292,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", - "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", "cpu": [ "arm64" ], @@ -1170,9 +1306,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", - "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", "cpu": [ "x64" ], @@ -1184,13 +1320,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", - "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1198,13 +1337,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", - "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1212,13 +1354,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", - "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1226,13 +1371,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", - "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1240,13 +1388,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", - "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1254,13 +1405,16 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", - "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1268,13 +1422,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", - "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1282,13 +1439,16 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", - "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1296,13 +1456,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", - "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1310,13 +1473,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", - "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1324,13 +1490,16 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", - "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1338,13 +1507,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", - "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1352,13 +1524,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", - "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1366,9 +1541,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", - "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", "cpu": [ "x64" ], @@ -1380,9 +1555,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", - "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", "cpu": [ "arm64" ], @@ -1394,9 +1569,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", - "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", "cpu": [ "arm64" ], @@ -1408,9 +1583,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", - "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", "cpu": [ "ia32" ], @@ -1422,9 +1597,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", - "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", "cpu": [ "x64" ], @@ -1436,9 +1611,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", - "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", "cpu": [ "x64" ], @@ -1475,20 +1650,21 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", - "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "version": "25.9.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.5.tgz", + "integrity": "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.18.0" + "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@types/node-fetch": { "version": "2.6.13", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "@types/node": "*", "form-data": "^4.0.4" @@ -1498,8 +1674,8 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "license": "MIT", - "optional": true + "dev": true, + "license": "MIT" }, "node_modules/@vitest/expect": { "version": "3.2.7", @@ -1620,8 +1796,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -1629,21 +1805,12 @@ "node": ">=6.5" } }, - "node_modules/adm-zip": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", - "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", - "license": "MIT", - "engines": { - "node": ">=12.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 14" } @@ -1652,8 +1819,8 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -1675,13 +1842,14 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT", - "optional": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, "funding": [ { "type": "github", @@ -1696,15 +1864,14 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/bignumber.js": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": "*" } @@ -1714,14 +1881,15 @@ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, "license": "MIT" }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause", - "optional": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/cac": { "version": "6.7.14", @@ -1737,8 +1905,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1774,12 +1942,22 @@ "node": ">= 16" } }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1791,8 +1969,8 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", - "license": "MIT", - "optional": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { "version": "12.1.0", @@ -1807,8 +1985,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 12" } @@ -1817,7 +1995,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -1845,6 +2023,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -1862,6 +2041,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -1879,8 +2059,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=0.4.0" } @@ -1889,6 +2069,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -1898,14 +2079,15 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, "license": "MIT" }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -1919,8 +2101,8 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -1929,6 +2111,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1938,6 +2121,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1951,11 +2135,11 @@ "license": "MIT" }, "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -1967,8 +2151,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -1983,12 +2167,13 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, "license": "MIT" }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1999,38 +2184,39 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -2053,16 +2239,16 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=6" } }, "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2073,8 +2259,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT", - "optional": true + "dev": true, + "license": "MIT" }, "node_modules/fdir": { "version": "6.5.0", @@ -2098,6 +2284,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, "funding": [ { "type": "github", @@ -2109,7 +2296,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -2118,18 +2304,29 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/fetch-blob/node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/flatbuffers": { "version": "25.9.23", "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", + "dev": true, "license": "Apache-2.0" }, "node_modules/form-data": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2141,12 +2338,33 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "fetch-blob": "^3.1.2" }, @@ -2173,18 +2391,18 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", - "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gaxios": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", - "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.3.1.tgz", + "integrity": "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", @@ -2198,8 +2416,8 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -2217,8 +2435,8 @@ "version": "8.1.2", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", @@ -2232,8 +2450,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -2257,8 +2475,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -2271,6 +2489,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "boolean": "^3.0.1", @@ -2288,6 +2507,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, "license": "MIT", "dependencies": { "define-properties": "^1.2.1", @@ -2301,11 +2521,11 @@ } }, "node_modules/google-auth-library": { - "version": "10.6.2", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", - "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.1.tgz", + "integrity": "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -2322,8 +2542,8 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "dev": true, "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=14" } @@ -2332,6 +2552,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2350,12 +2571,14 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz", "integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==", + "dev": true, "license": "ISC" }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -2368,8 +2591,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" }, @@ -2381,8 +2604,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -2397,8 +2620,8 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -2410,8 +2633,8 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "agent-base": "^7.1.2", "debug": "4" @@ -2424,8 +2647,8 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "ms": "^2.0.0" } @@ -2441,8 +2664,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "bignumber.js": "^9.0.0" } @@ -2451,14 +2674,15 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, "license": "ISC" }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -2469,8 +2693,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" @@ -2480,6 +2704,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/kokoro-js/-/kokoro-js-1.2.1.tgz", "integrity": "sha512-oq0HZJWis3t8lERkMJh84WLU86dpYD0EuBPtqYnLlQzyFP1OkyBRDcweAqCfhNOpltyN9j/azp1H6uuC47gShw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@huggingface/transformers": "^3.5.1", @@ -2490,6 +2715,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, "license": "Apache-2.0" }, "node_modules/loupe": { @@ -2513,6 +2739,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^4.0.0" @@ -2525,8 +2752,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.4" } @@ -2535,8 +2762,8 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 0.6" } @@ -2545,8 +2772,8 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "mime-db": "1.52.0" }, @@ -2554,17 +2781,40 @@ "node": ">= 0.6" } }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.15", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", - "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -2585,6 +2835,7 @@ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "deprecated": "Use your platform's native DOMException instead", + "dev": true, "funding": [ { "type": "github", @@ -2596,7 +2847,6 @@ } ], "license": "MIT", - "optional": true, "engines": { "node": ">=10.5.0" } @@ -2605,8 +2855,8 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -2626,21 +2876,24 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/onnxruntime-common": { - "version": "1.24.3", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.3.tgz", - "integrity": "sha512-GeuPZO6U/LBJXvwdaqHbuUmoXiEdeCjWi/EG7Y1HNnDwJYuk6WUbNXpF6luSUY8yASul3cmUlLGrCCL1ZgVXqA==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", + "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", + "dev": true, "license": "MIT" }, "node_modules/onnxruntime-node": { - "version": "1.24.3", - "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.24.3.tgz", - "integrity": "sha512-JH7+czbc8ALA819vlTgcV+Q214/+VjGeBHDjX81+ZCD0PCVCIFGFNtT0V4sXG/1JXypKPgScQcB3ij/hk3YnTg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", + "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "os": [ @@ -2649,37 +2902,39 @@ "linux" ], "dependencies": { - "adm-zip": "^0.5.16", "global-agent": "^3.0.0", - "onnxruntime-common": "1.24.3" + "onnxruntime-common": "1.21.0", + "tar": "^7.0.1" } }, "node_modules/onnxruntime-web": { - "version": "1.26.0-dev.20260416-b7804b056c", - "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.26.0-dev.20260416-b7804b056c.tgz", - "integrity": "sha512-MD6Ss4GSpQBo6zqoJzyT9LRbKYs7x/JVN23FT24EcEvlqF4VuzPOeH6X38orZPKHQDbprn7K+SBpu0/mj2CQiw==", + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", + "dev": true, "license": "MIT", "dependencies": { "flatbuffers": "^25.1.24", "guid-typescript": "^1.0.9", "long": "^5.2.3", - "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", + "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", "platform": "^1.3.6", "protobufjs": "^7.2.4" } }, "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { - "version": "1.24.0-dev.20251116-b39e144322", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.0-dev.20251116-b39e144322.tgz", - "integrity": "sha512-BOoomdHYmNRL5r4iQ4bMvsl2t0/hzVQ3OM3PHD0gxeXu1PmggqBv3puZicEUVOA3AtHHYmqZtjMj9FOfGrATTw==", + "version": "1.22.0-dev.20250409-89f8206ba4", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", + "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", + "dev": true, "license": "MIT" }, "node_modules/openai": { "version": "4.104.0", "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -2709,56 +2964,25 @@ "version": "18.19.130", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "undici-types": "~5.26.4" } }, - "node_modules/openai/node_modules/form-data-encoder": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", - "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", - "license": "MIT", - "optional": true - }, - "node_modules/openai/node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" - }, - "engines": { - "node": ">= 12.20" - } - }, "node_modules/openai/node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT", - "optional": true - }, - "node_modules/openai/node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 14" - } + "dev": true, + "license": "MIT" }, "node_modules/p-retry": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" @@ -2788,6 +3012,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/phonemizer/-/phonemizer-1.2.1.tgz", "integrity": "sha512-v0KJ4mi2T4Q7eJQ0W15Xd4G9k4kICSXE8bpDeJ8jisL4RyJhNWsweKTOi88QXFc4r4LZlz5jVL5lCHhkpdT71A==", + "dev": true, "license": "Apache-2.0" }, "node_modules/picocolors": { @@ -2814,44 +3039,45 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true, "license": "MIT" }, "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.59.1" + "playwright-core": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/postcss": { - "version": "8.5.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", - "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -2869,7 +3095,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -2881,6 +3107,7 @@ "version": "7.6.5", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -2904,8 +3131,8 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 4" } @@ -2914,6 +3141,7 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "boolean": "^3.0.1", @@ -2928,9 +3156,9 @@ } }, "node_modules/rollup": { - "version": "4.62.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", - "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", "dev": true, "license": "MIT", "dependencies": { @@ -2944,31 +3172,32 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.62.2", - "@rollup/rollup-android-arm64": "4.62.2", - "@rollup/rollup-darwin-arm64": "4.62.2", - "@rollup/rollup-darwin-x64": "4.62.2", - "@rollup/rollup-freebsd-arm64": "4.62.2", - "@rollup/rollup-freebsd-x64": "4.62.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", - "@rollup/rollup-linux-arm-musleabihf": "4.62.2", - "@rollup/rollup-linux-arm64-gnu": "4.62.2", - "@rollup/rollup-linux-arm64-musl": "4.62.2", - "@rollup/rollup-linux-loong64-gnu": "4.62.2", - "@rollup/rollup-linux-loong64-musl": "4.62.2", - "@rollup/rollup-linux-ppc64-gnu": "4.62.2", - "@rollup/rollup-linux-ppc64-musl": "4.62.2", - "@rollup/rollup-linux-riscv64-gnu": "4.62.2", - "@rollup/rollup-linux-riscv64-musl": "4.62.2", - "@rollup/rollup-linux-s390x-gnu": "4.62.2", - "@rollup/rollup-linux-x64-gnu": "4.62.2", - "@rollup/rollup-linux-x64-musl": "4.62.2", - "@rollup/rollup-openbsd-x64": "4.62.2", - "@rollup/rollup-openharmony-arm64": "4.62.2", - "@rollup/rollup-win32-arm64-msvc": "4.62.2", - "@rollup/rollup-win32-ia32-msvc": "4.62.2", - "@rollup/rollup-win32-x64-gnu": "4.62.2", - "@rollup/rollup-win32-x64-msvc": "4.62.2", + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", "fsevents": "~2.3.2" } }, @@ -2976,6 +3205,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -2990,14 +3220,13 @@ "url": "https://feross.org/support" } ], - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/sarvamai": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/sarvamai/-/sarvamai-1.1.6.tgz", - "integrity": "sha512-kfrKQIk8xlUwvWeuhMF4ljwjuMWPelzuBe+4BlUD3qeoEisCfKLTq/MX2FfkcJ6spnMrwPDix96ngmhyLj2Q9w==", - "optional": true, + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/sarvamai/-/sarvamai-1.1.8.tgz", + "integrity": "sha512-u5qhfTfTy2IIpyXwsH6cJPJcM0a8PUdo5ZRObxRKZflU8lpGTi+VKXMq3hHzO07/9bSqWD2Rrt07ElX3YurjjQ==", + "dev": true, "dependencies": { "ws": "^8.16.0" }, @@ -3006,9 +3235,10 @@ } }, "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -3021,12 +3251,14 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, "license": "MIT" }, "node_modules/serialize-error": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, "license": "MIT", "dependencies": { "type-fest": "^0.13.1" @@ -3042,6 +3274,7 @@ "version": "0.34.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3103,6 +3336,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, "license": "BSD-3-Clause" }, "node_modules/stackback": { @@ -3132,6 +3366,23 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -3197,13 +3448,14 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "optional": true + "dev": true, + "license": "MIT" }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, "license": "0BSD", "optional": true }, @@ -3211,6 +3463,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" @@ -3234,9 +3487,10 @@ } }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, "license": "MIT" }, "node_modules/vite": { @@ -3426,28 +3680,28 @@ } }, "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">= 8" + "node": ">= 14" } }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "optional": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -3471,11 +3725,11 @@ } }, "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=10.0.0" }, @@ -3491,6 +3745,16 @@ "optional": true } } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } } } } diff --git a/package.json b/package.json index bebd35b..7cc1a5e 100644 --- a/package.json +++ b/package.json @@ -22,31 +22,26 @@ "test:watch": "vitest" }, "peerDependencies": { + "@elevenlabs/elevenlabs-js": ">=2", + "@google/genai": ">=1", + "@huggingface/transformers": "^3.5.1 || ^4.2.0", "@playwright/test": ">=1.59.0", - "playwright": ">=1.59.0" + "kokoro-js": "^1.2.1", + "openai": ">=4", + "playwright": ">=1.59.0", + "sarvamai": ">=1" }, "dependencies": { - "@huggingface/transformers": "^4.2.0", "commander": "^12.0.0", - "gsap": "^3.15.0", - "kokoro-js": "^1.2.1" + "gsap": "^3.15.0" }, "overrides": { - "kokoro-js": { - "@huggingface/transformers": "$@huggingface/transformers" - }, "ws": "^8.21.0", "form-data": "^4.0.6", "vite": "^7.3.5", "esbuild": "^0.28.1", "protobufjs": "^7.6.3" }, - "optionalDependencies": { - "@elevenlabs/elevenlabs-js": "^2.0.0", - "@google/genai": "^1.0.0", - "openai": "^4.0.0", - "sarvamai": "^1.0.0" - }, "publishConfig": { "access": "public" }, @@ -61,10 +56,36 @@ "scripts" ], "devDependencies": { + "@elevenlabs/elevenlabs-js": "^2.63.0", + "@google/genai": "^1.52.0", + "@huggingface/transformers": "^3.5.1", "@playwright/test": "^1.59.1", "@types/node": "^25.5.0", + "kokoro-js": "^1.2.1", + "openai": "^4.104.0", "playwright": "^1.59.1", + "sarvamai": "^1.1.8", "typescript": "^5.5.0", "vitest": "^3.2.6" + }, + "peerDependenciesMeta": { + "@elevenlabs/elevenlabs-js": { + "optional": true + }, + "@google/genai": { + "optional": true + }, + "@huggingface/transformers": { + "optional": true + }, + "kokoro-js": { + "optional": true + }, + "openai": { + "optional": true + }, + "sarvamai": { + "optional": true + } } } From 016041cb5f5ba62d3fa127487b4f2cac3e6794d9 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:00:28 +0200 Subject: [PATCH 3/9] feat(cli): report engine availability and install commands `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. --- src/doctor.ts | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/init.ts | 26 +++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/doctor.ts b/src/doctor.ts index 16e6d9e..9830ae1 100644 --- a/src/doctor.ts +++ b/src/doctor.ts @@ -1,6 +1,19 @@ import { execFileSync } from 'node:child_process'; import { existsSync } from 'node:fs'; import { loadConfig } from './config.js'; +import { + detectInstallMode, + installCommand, + isDepInstalled, + KOKORO_DEP, + OPENAI_DEP, + ELEVENLABS_DEP, + GEMINI_DEP, + SARVAM_DEP, + TRANSFORMERS_DEP, + WHISPER_DEP, + type OptionalDepSpec, +} from './optional-deps.js'; interface CheckResult { name: string; @@ -103,6 +116,57 @@ export async function runDoctor(cwd: string = process.cwd()): Promise = [ + ['kokoro', KOKORO_DEP, true], + ['openai', OPENAI_DEP, true], + ['elevenlabs', ELEVENLABS_DEP, true], + ['gemini', GEMINI_DEP, true], + ['sarvam', SARVAM_DEP, true], + ['transformers', TRANSFORMERS_DEP, true], + ['transcribe', WHISPER_DEP, false], + ]; + + const results: CheckResult[] = [ + { name: 'install mode', status: 'ok', message: mode }, + ]; + let anyEngine = false; + + for (const [name, spec, isVoiceEngine] of specs) { + if (isDepInstalled(spec)) { + if (isVoiceEngine) anyEngine = true; + results.push({ name: `engine/${name}`, status: 'ok', message: 'installed' }); + } else { + results.push({ + name: `engine/${name}`, + status: 'warn', + message: `not installed. ${installCommand(spec, mode)}`, + }); + } + } + + if (!anyEngine) { + results.push({ + name: 'engines', + status: 'warn', + message: `No npm TTS engine installed. ${installCommand(KOKORO_DEP, mode)} (or use engines.mlxAudio)`, + }); + } + return results; } diff --git a/src/init.ts b/src/init.ts index 7a804d8..151c34d 100644 --- a/src/init.ts +++ b/src/init.ts @@ -5,6 +5,16 @@ import { generateDemoScript, generateScenesSkeleton, } from './parse-playwright.js'; +import { + installCommand, + isDepInstalled, + KOKORO_DEP, + OPENAI_DEP, + ELEVENLABS_DEP, + GEMINI_DEP, + SARVAM_DEP, + TRANSFORMERS_DEP, +} from './optional-deps.js'; async function writeIfMissing(filePath: string, content: string): Promise { try { @@ -146,6 +156,22 @@ export async function init(cwd: string = process.cwd()): Promise { console.log(' 1. Edit demos/example.demo.ts'); console.log(' 2. Run: npx argo record example'); console.log(' 3. Run: npx argo pipeline example'); + printEngineHintIfMissing(); +} + +/** Scaffolding is the first place a new user can discover that no TTS engine + * is installed. Say so here rather than letting the first `pipeline` run + * fail on it. Silent when an engine is already present. */ +function printEngineHintIfMissing(): void { + const specs = [KOKORO_DEP, OPENAI_DEP, ELEVENLABS_DEP, GEMINI_DEP, SARVAM_DEP, TRANSFORMERS_DEP]; + if (specs.some(isDepInstalled)) return; + // Always the project-mode command: `init` has just scaffolded a project + // here, so that is where the engine belongs even when Argo itself was + // invoked globally or through npx. + console.log('\nNo TTS engine is installed yet. Pick one:'); + console.log(` local, no API key: ${installCommand(KOKORO_DEP, 'project')}`); + console.log(` cloud, needs a key: ${installCommand(OPENAI_DEP, 'project')}`); + console.log(' see all engines: npx argo doctor'); } export interface InitFromOptions { From 0ea96b532d2924d07ed3b490144a2930d52269ee Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:55:30 +0200 Subject: [PATCH 4/9] test: cover optional dependency resolution 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. --- tests/optional-deps.test.ts | 159 +++++++++++++++++++++++++++++++++ tests/optional-imports.test.ts | 55 ++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 tests/optional-deps.test.ts create mode 100644 tests/optional-imports.test.ts diff --git a/tests/optional-deps.test.ts b/tests/optional-deps.test.ts new file mode 100644 index 0000000..363044f --- /dev/null +++ b/tests/optional-deps.test.ts @@ -0,0 +1,159 @@ +import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { + installCommand, + isModuleNotFound, + missingDependencyError, + importOptional, + isDepInstalled, + detectInstallMode, + resetInstallModeCache, + KOKORO_DEP, + OPENAI_DEP, + WHISPER_DEP, + type OptionalDepSpec, + type InstallMode, +} from '../src/optional-deps.js'; + +/** A spec pointing at a package that is deliberately not installed. */ +const MISSING_DEP: OptionalDepSpec = { + feature: 'a package that does not exist', + project: ['argo-no-such-package-xyz'], + global: ['argo-no-such-package-xyz'], +}; + +describe('installCommand', () => { + const cases: Array<[name: string, spec: OptionalDepSpec, mode: InstallMode, expected: string]> = [ + ['project mode installs plainly', OPENAI_DEP, 'project', 'npm i openai'], + ['global mode adds -g', OPENAI_DEP, 'global', 'npm i -g openai'], + // Kokoro names both packages in ONE global command: two separate + // `npm i -g` runs do not dedupe and leave a second copy of onnxruntime + // (~840MB vs ~410MB). In project mode npm hoists it, so one name is enough. + [ + 'global Kokoro names both packages in one command', + KOKORO_DEP, + 'global', + 'npm i -g kokoro-js @huggingface/transformers@^3', + ], + ['project Kokoro omits the hoisted transformers', KOKORO_DEP, 'project', 'npm i kokoro-js'], + [ + 'npx composes packages onto the invocation', + OPENAI_DEP, + 'npx', + 'npx -p @argo-video/cli -p openai -- argo ', + ], + ]; + + it.each(cases)('%s', (_name, spec, mode, expected) => { + expect(installCommand(spec, mode)).toBe(expected); + }); +}); + +describe('isModuleNotFound', () => { + it('recognises both ESM and CJS resolution failures', () => { + expect(isModuleNotFound({ code: 'ERR_MODULE_NOT_FOUND' })).toBe(true); + expect(isModuleNotFound({ code: 'MODULE_NOT_FOUND' })).toBe(true); + }); + + it('does not claim unrelated errors', () => { + expect(isModuleNotFound(new Error('boom'))).toBe(false); + expect(isModuleNotFound({ code: 'ECONNREFUSED' })).toBe(false); + expect(isModuleNotFound(null)).toBe(false); + expect(isModuleNotFound(undefined)).toBe(false); + }); +}); + +describe('missingDependencyError', () => { + it('names the feature, the package, and the command', () => { + const err = missingDependencyError(WHISPER_DEP); + expect(err.message).toContain('Whisper word-level transcription'); + expect(err.message).toContain("'@huggingface/transformers'"); + expect(err.message).toContain('Install it with:'); + }); + + it('strips version ranges from the package name it reports', () => { + const spec: OptionalDepSpec = { + feature: 'test', + project: ['some-pkg@^3'], + global: ['some-pkg@^3'], + }; + expect(missingDependencyError(spec).message).toContain("'some-pkg'"); + expect(missingDependencyError(spec).message).not.toContain("'some-pkg@^3'"); + }); +}); + +describe('importOptional', () => { + it('returns the module when the import succeeds', async () => { + const mod = await importOptional(async () => ({ ok: 1 }), OPENAI_DEP); + expect(mod).toEqual({ ok: 1 }); + }); + + it('converts a missing package into an actionable error', async () => { + const notFound = Object.assign(new Error('nope'), { code: 'ERR_MODULE_NOT_FOUND' }); + await expect( + importOptional(() => Promise.reject(notFound), MISSING_DEP), + ).rejects.toThrow(/optional dependency and is not installed/); + }); + + it('lets a genuine fault inside an installed package propagate unchanged', async () => { + // A package that IS installed but throws on load must not be reported as + // missing, or the user is told to install something they already have. + const boom = new Error('the package itself is broken'); + await expect( + importOptional(() => Promise.reject(boom), OPENAI_DEP), + ).rejects.toThrow('the package itself is broken'); + }); + + it('does not blame the package when a transitive dep is what went missing', async () => { + // onnxruntime-node require()s a per-arch native binding at runtime. On a + // machine without a matching prebuilt, that surfaces as MODULE_NOT_FOUND + // from three levels down. Telling the user to install openai, which they + // demonstrably have, sends them in circles. + const transitive = Object.assign( + new Error("Cannot find module './bin/napi-v3/linux/arm64/binding.node'"), + { code: 'MODULE_NOT_FOUND' }, + ); + await expect( + importOptional(() => Promise.reject(transitive), OPENAI_DEP), + ).rejects.toThrow(/binding\.node/); + }); + + it('preserves the original error as `cause`', async () => { + const notFound = Object.assign(new Error('nope'), { code: 'ERR_MODULE_NOT_FOUND' }); + const err = await importOptional(() => Promise.reject(notFound), MISSING_DEP).catch( + (e: Error & { cause?: unknown }) => e, + ); + expect(err.cause).toBe(notFound); + }); +}); + +describe('isDepInstalled', () => { + it('finds a package that is present', () => { + // openai is a devDependency of this repo, so it resolves during tests. + expect(isDepInstalled(OPENAI_DEP)).toBe(true); + }); + + it('reports a package that is absent', () => { + expect(isDepInstalled(MISSING_DEP)).toBe(false); + }); + + it('ignores a version range attached to the specifier', () => { + expect(isDepInstalled({ ...OPENAI_DEP, project: ['openai@^4'] })).toBe(true); + }); +}); + +describe('detectInstallMode', () => { + beforeEach(() => resetInstallModeCache()); + + it('reports project mode when running from the source checkout', () => { + // Tests run from src/, which is not inside any node_modules. + expect(detectInstallMode()).toBe('project'); + }); + + it('caches the result instead of recomputing', () => { + const first = detectInstallMode(); + const spy = vi.spyOn(process, 'cwd'); + expect(detectInstallMode()).toBe(first); + expect(spy).not.toHaveBeenCalled(); + spy.mockRestore(); + }); +}); diff --git a/tests/optional-imports.test.ts b/tests/optional-imports.test.ts new file mode 100644 index 0000000..f6463bb --- /dev/null +++ b/tests/optional-imports.test.ts @@ -0,0 +1,55 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync, globSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join, relative } from 'node:path'; + +const SRC = join(dirname(fileURLToPath(import.meta.url)), '..', 'src'); + +/** Packages declared as optional peers in package.json. None may be reachable + * through a static import, or the whole install-footprint design collapses: + * a top-level import fails at module-link time and takes down every command, + * including ones that never touch TTS. */ +const OPTIONAL_PACKAGES = [ + 'kokoro-js', + '@huggingface/transformers', + 'openai', + '@elevenlabs/elevenlabs-js', + '@google/genai', + 'sarvamai', +]; + +/** `import x from 'pkg'` / `export * from 'pkg'` but NOT `import('pkg')`. + * The negative lookbehind on `(` is what separates static from dynamic. */ +function staticImportOf(pkg: string): RegExp { + const escaped = pkg.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return new RegExp(`(? { + // All six are devDependencies, so they resolve during tests. Nothing else in + // the suite can notice a regression from `await import(x)` back to a + // top-level `import x from`. This test is the only guard. + const files = globSync('**/*.ts', { cwd: SRC }) + .map((f) => join(SRC, f)) + .filter((f) => !f.endsWith('.d.ts')); + + it('finds source files to scan', () => { + expect(files.length).toBeGreaterThan(20); + }); + + for (const pkg of OPTIONAL_PACKAGES) { + it(`no static import of ${pkg}`, () => { + const pattern = staticImportOf(pkg); + const offenders = files + .filter((file) => { + const src = readFileSync(file, 'utf-8'); + return src.split('\n').some((line) => { + const code = line.replace(/\/\/.*$/, '').replace(/^\s*\*.*$/, ''); + return pattern.test(code); + }); + }) + .map((f) => relative(SRC, f)); + expect(offenders).toEqual([]); + }); + } +}); From 8b2b7f7e7a103ddd5d36058d26d262fb7cbe3844 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:00:32 +0200 Subject: [PATCH 5/9] docs: document optional engine dependencies 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. --- CLAUDE.md | 10 ++++ README.md | 56 +++++++++++++++++---- skills/argo-guide/SKILL.md | 2 + skills/argo-guide/references/tts-engines.md | 13 ++++- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ac25301..e63b6fa 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,6 +16,16 @@ Argo turns Playwright demo scripts into polished product demo videos with AI voi - Kokoro TTS defaults: model `onnx-community/Kokoro-82M-v1.0-ONNX`, dtype `q8` - Clear TTS cache if voiceover text changes: `rm -rf .argo//clips` +## Optional Engine Dependencies (`src/optional-deps.ts`) + +All six TTS/STT SDKs (`kokoro-js`, `@huggingface/transformers`, `openai`, `@elevenlabs/elevenlabs-js`, `@google/genai`, `sarvamai`) are **optional peer dependencies**, not `dependencies` or `optionalDependencies`. This is deliberate: npm installs `optionalDependencies` by default (the field only tolerates install *failure*), while `peerDependenciesMeta.optional` is the one field npm never auto-installs. Base install is ~27 MB; a Kokoro user reaches ~435 MB only if they ask for it. + +- Every adapter loads its SDK through `importOptional()`, which converts `ERR_MODULE_NOT_FOUND` into an install hint and lets every other failure propagate untouched. Never replace it with a bare `catch` that assumes "missing package" (that was the old behaviour and it misreported broken installs). +- `src/tts/transcribe.ts` MUST keep its `@huggingface/transformers` import dynamic. A top-level import there is reachable from `src/cli.ts`, so it breaks *every* command (`validate`, `export`, `doctor`) when the package is absent, in all three install modes. This was the single blocker to the whole design. +- `@huggingface/transformers` is declared `^3.5.1 || ^4.2.0` on purpose. `kokoro-js@1.2.1` wants `^3.5.1`; pinning Argo to `^4` forces a second nested copy plus a second ONNX runtime (~765 MB vs ~410 MB) because `overrides` only apply in a root `package.json` and stop working once Argo is a dependency. Word-level Whisper timestamps are verified working on 3.8.1. +- `detectInstallMode()` distinguishes project / global / npx, because the correct install command differs. Global trees do not hoist, so Kokoro needs `npm i -g kokoro-js @huggingface/transformers@^3` in **one** command; two separate `npm i -g` runs produce two ONNX copies (~840 MB vs ~410 MB). Detection resolves `@argo-video/cli` from the cwd and compares identity with the running copy, which keeps pnpm, nested npm, and Yarn PnP working without path-string special cases. +- Surfaces that report engine availability: `argo doctor` (full table), `argo init` (hint when nothing is installed), and the adapters' runtime errors. Keep them consistent when adding an engine. + ## Publishing - Package: `@argo-video/cli` (npm org: `@argo-video`) diff --git a/README.md b/README.md index dc6b704..535d939 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,15 @@ Write a demo script with Playwright. Add a scenes manifest. Run one command. Get ## Quick start ```bash -# Install +# Install the core (about 27 MB, no TTS engine yet) npm i -D @argo-video/cli +# Add the TTS engine you want. Engines are optional peer dependencies, +# so you only pay for the one you use. Run `npx argo doctor` any time to +# see which engines are installed and the exact command for your setup. +npm i kokoro-js # local, free, no API key (~410 MB of ONNX runtime) +npm i openai # cloud, needs OPENAI_API_KEY (~20 MB) + # Initialize project npx argo init @@ -368,15 +374,45 @@ choco install ffmpeg # Windows }); ``` - | Engine | Type | Install | API Key | - |--------|------|---------|---------| - | `engines.kokoro()` | local | built-in | none | - | `engines.mlxAudio()` | local | `pip install mlx-audio` | none | - | `engines.openai()` | cloud | `npm i openai` | `OPENAI_API_KEY` | - | `engines.elevenlabs()` | cloud | `npm i @elevenlabs/elevenlabs-js` | `ELEVENLABS_API_KEY` | - | `engines.gemini()` | cloud | `npm i @google/genai` | `GEMINI_API_KEY` | - | `engines.sarvam()` | cloud | `npm i sarvamai` | `SARVAM_API_KEY` | - | `engines.transformers()` | local | built-in | none | + Every engine is an **optional peer dependency**: npm does not install it + for you, so the base package stays small. Install the one you use. + + | Engine | Type | Install | Size | API Key | + |--------|------|---------|------|---------| + | `engines.kokoro()` | local | `npm i kokoro-js` | ~410 MB | none | + | `engines.mlxAudio()` | local | `pip install mlx-audio` | n/a (Python) | none | + | `engines.openai()` | cloud | `npm i openai` | ~20 MB | `OPENAI_API_KEY` | + | `engines.elevenlabs()` | cloud | `npm i @elevenlabs/elevenlabs-js` | ~88 MB | `ELEVENLABS_API_KEY` | + | `engines.gemini()` | cloud | `npm i @google/genai` | ~36 MB | `GEMINI_API_KEY` | + | `engines.sarvam()` | cloud | `npm i sarvamai` | ~7 MB | `SARVAM_API_KEY` | + | `engines.transformers()` | local | `npm i @huggingface/transformers` | ~380 MB | none | + + Sizes are `node_modules` on disk for that package alone in an empty + project. They do not simply add up, because engines share transitive + dependencies with Argo. Measured end to end, a project install comes to + about 27 MB with no engine, 47 MB with OpenAI, and 435 MB with Kokoro. + + The commands above are for a project-local install. A **global** install + (`npm i -g @argo-video/cli`) needs `-g` on the engine too, and Kokoro + needs both packages in **one** command, because separate global installs + do not deduplicate and you end up with two copies of the ONNX runtime: + + ```bash + npm i -g kokoro-js @huggingface/transformers@^3 # one command, ~410 MB + ``` + + With **npx**, compose the engine into the same invocation: + + ```bash + npx -p @argo-video/cli -p openai -- argo pipeline example + ``` + + `npx argo doctor` prints the right command for whichever of the three + you are using. + + Word-level transcription (`tts.transcribe`) needs + `@huggingface/transformers`. Installing `kokoro-js` already brings it in + on a project install, so there is usually nothing extra to do. **Transformers.js** — Use any HuggingFace `text-to-speech` model locally. Supertonic, or any future ONNX TTS model: diff --git a/skills/argo-guide/SKILL.md b/skills/argo-guide/SKILL.md index f582802..618f0e4 100644 --- a/skills/argo-guide/SKILL.md +++ b/skills/argo-guide/SKILL.md @@ -16,6 +16,8 @@ Argo turns Playwright demo scripts into polished product demo videos with AI voi ## Prerequisites +**No TTS engine ships by default.** Every engine is an optional peer dependency. Install one before running a pipeline: `npm i kokoro-js` (local, no API key) or `npm i openai` (cloud, needs `OPENAI_API_KEY`). Run `npx argo doctor` to see which engines are present and the exact install command for this project. + 1. **`@argo-video/cli`** in `devDependencies` — install with `npm i -D @argo-video/cli` if missing 2. **`argo.config.mjs`** in project root — scaffold with `npx argo init` if missing (use `.mjs` to avoid ESM warnings) 3. **Playwright browsers** — `npx playwright install chromium` (or `webkit` for best macOS quality) diff --git a/skills/argo-guide/references/tts-engines.md b/skills/argo-guide/references/tts-engines.md index 8faafe7..a574f56 100644 --- a/skills/argo-guide/references/tts-engines.md +++ b/skills/argo-guide/references/tts-engines.md @@ -15,15 +15,24 @@ export default defineConfig({ }); ``` +Every engine is an optional peer dependency. npm does not install any of +them automatically, so a fresh `@argo-video/cli` has no TTS engine until one +is added. `npx argo doctor` lists which are present. + | Engine | Type | Install | Voices | |--------|------|---------|--------| -| `engines.kokoro()` | local | built-in | `af_heart`, `am_michael` | +| `engines.kokoro()` | local | `npm i kokoro-js` | `af_heart`, `am_michael` | | `engines.openai()` | cloud | `npm i openai` | `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer` | | `engines.elevenlabs()` | cloud | `npm i @elevenlabs/elevenlabs-js` | ElevenLabs voice IDs | | `engines.gemini()` | cloud | `npm i @google/genai` | Gemini voice names | | `engines.sarvam()` | cloud | `npm i sarvamai` | `meera` + Indian language voices | | `engines.mlxAudio()` | local | `pip install mlx-audio` | model-dependent (Apple Silicon only) | -| `engines.transformers()` | local | built-in | any HuggingFace `text-to-speech` model | +| `engines.transformers()` | local | `npm i @huggingface/transformers` | any HuggingFace `text-to-speech` model | + +Those commands assume a project-local Argo. For a global install add `-g`, +and install Kokoro's two packages in one command so npm deduplicates the +ONNX runtime: `npm i -g kokoro-js @huggingface/transformers@^3`. For npx, +compose them: `npx -p @argo-video/cli -p openai -- argo pipeline `. Cloud engines read API keys from environment variables (`OPENAI_API_KEY`, `ELEVENLABS_API_KEY`, `GEMINI_API_KEY`, `SARVAM_API_KEY`) or accept `apiKey` in factory options. From 3a33bdde8038e6fd4493d3f2c42985ae527ba216 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:25:33 +0200 Subject: [PATCH 6/9] fix(deps): pin install hints, harden probes --- CLAUDE.md | 4 +- README.md | 12 +-- skills/argo-guide/SKILL.md | 2 +- skills/argo-guide/references/tts-engines.md | 6 +- src/optional-deps.ts | 89 +++++++++++---- tests/optional-deps.test.ts | 113 ++++++++++++++++++-- 6 files changed, 188 insertions(+), 38 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e63b6fa..8f66f34 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,9 @@ All six TTS/STT SDKs (`kokoro-js`, `@huggingface/transformers`, `openai`, `@elev - Every adapter loads its SDK through `importOptional()`, which converts `ERR_MODULE_NOT_FOUND` into an install hint and lets every other failure propagate untouched. Never replace it with a bare `catch` that assumes "missing package" (that was the old behaviour and it misreported broken installs). - `src/tts/transcribe.ts` MUST keep its `@huggingface/transformers` import dynamic. A top-level import there is reachable from `src/cli.ts`, so it breaks *every* command (`validate`, `export`, `doctor`) when the package is absent, in all three install modes. This was the single blocker to the whole design. - `@huggingface/transformers` is declared `^3.5.1 || ^4.2.0` on purpose. `kokoro-js@1.2.1` wants `^3.5.1`; pinning Argo to `^4` forces a second nested copy plus a second ONNX runtime (~765 MB vs ~410 MB) because `overrides` only apply in a root `package.json` and stop working once Argo is a dependency. Word-level Whisper timestamps are verified working on 3.8.1. -- `detectInstallMode()` distinguishes project / global / npx, because the correct install command differs. Global trees do not hoist, so Kokoro needs `npm i -g kokoro-js @huggingface/transformers@^3` in **one** command; two separate `npm i -g` runs produce two ONNX copies (~840 MB vs ~410 MB). Detection resolves `@argo-video/cli` from the cwd and compares identity with the running copy, which keeps pnpm, nested npm, and Yarn PnP working without path-string special cases. +- The permissive peer *range* does not license a permissive install *hint*. `TRANSFORMERS_DEP`, `WHISPER_DEP` and `MUSICGEN_DEP` all print `@huggingface/transformers@3`, because `latest` is 4.x and a bare `npm i` next to an existing `kokoro-js` produces exactly the two-runtime tree above. Every command Argo prints must resolve to the major `kokoro-js` shares; `tests/optional-deps.test.ts` pins this. Drop the pin only when `kokoro-js` moves to v4. +- Neither `isDepInstalled()` nor `detectInstallMode()` may propagate a resolver failure. A probe can fail without the package being absent: `ERR_INVALID_PACKAGE_CONFIG` from an interrupted install, `ERR_PACKAGE_PATH_NOT_EXPORTED` from an `exports` map with no matching condition (which this package shipped once, see Publishing). Both run inside `importOptional`'s `catch`, where a throw replaces the import error the user needs, and `argo doctor` calls `detectInstallMode()` before anything else, so a throw there costs the whole table on exactly the broken tree the command exists to diagnose. `isDepInstalled` answers "not known to be absent" and `detectInstallMode` falls back to `project`. Both recover only on errors carrying a `code`: a bug in Argo surfaces as a bare `TypeError` and must still throw. +- `detectInstallMode()` distinguishes project / global / npx, because the correct install command differs. Global trees do not hoist, so Kokoro needs `npm i -g kokoro-js@1 @huggingface/transformers@3` in **one** command; two separate `npm i -g` runs produce two ONNX copies (~840 MB vs ~410 MB). Detection resolves `@argo-video/cli` from the cwd and compares identity with the running copy, which keeps pnpm, nested npm, and Yarn PnP working without path-string special cases. - Surfaces that report engine availability: `argo doctor` (full table), `argo init` (hint when nothing is installed), and the adapters' runtime errors. Keep them consistent when adding an engine. ## Publishing diff --git a/README.md b/README.md index 535d939..4839997 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ npm i -D @argo-video/cli # Add the TTS engine you want. Engines are optional peer dependencies, # so you only pay for the one you use. Run `npx argo doctor` any time to # see which engines are installed and the exact command for your setup. -npm i kokoro-js # local, free, no API key (~410 MB of ONNX runtime) +npm i kokoro-js@1 # local, free, no API key (~410 MB of ONNX runtime) npm i openai # cloud, needs OPENAI_API_KEY (~20 MB) # Initialize project @@ -352,8 +352,8 @@ import { defineConfig, demosProject, engines } from '@argo-video/cli'; ## Requirements -- **Node.js** >= 18 -- **Playwright** >= 1.40 (peer dependency) +- **Node.js** >= 20 (Playwright requires it) +- **Playwright** >= 1.59 (peer dependency) - **ffmpeg** — system install required for export ```bash @@ -379,13 +379,13 @@ choco install ffmpeg # Windows | Engine | Type | Install | Size | API Key | |--------|------|---------|------|---------| - | `engines.kokoro()` | local | `npm i kokoro-js` | ~410 MB | none | + | `engines.kokoro()` | local | `npm i kokoro-js@1` | ~410 MB | none | | `engines.mlxAudio()` | local | `pip install mlx-audio` | n/a (Python) | none | | `engines.openai()` | cloud | `npm i openai` | ~20 MB | `OPENAI_API_KEY` | | `engines.elevenlabs()` | cloud | `npm i @elevenlabs/elevenlabs-js` | ~88 MB | `ELEVENLABS_API_KEY` | | `engines.gemini()` | cloud | `npm i @google/genai` | ~36 MB | `GEMINI_API_KEY` | | `engines.sarvam()` | cloud | `npm i sarvamai` | ~7 MB | `SARVAM_API_KEY` | - | `engines.transformers()` | local | `npm i @huggingface/transformers` | ~380 MB | none | + | `engines.transformers()` | local | `npm i @huggingface/transformers@3` | ~380 MB | none | Sizes are `node_modules` on disk for that package alone in an empty project. They do not simply add up, because engines share transitive @@ -398,7 +398,7 @@ choco install ffmpeg # Windows do not deduplicate and you end up with two copies of the ONNX runtime: ```bash - npm i -g kokoro-js @huggingface/transformers@^3 # one command, ~410 MB + npm i -g kokoro-js@1 @huggingface/transformers@3 # one command, ~410 MB ``` With **npx**, compose the engine into the same invocation: diff --git a/skills/argo-guide/SKILL.md b/skills/argo-guide/SKILL.md index 618f0e4..eed1aa3 100644 --- a/skills/argo-guide/SKILL.md +++ b/skills/argo-guide/SKILL.md @@ -16,7 +16,7 @@ Argo turns Playwright demo scripts into polished product demo videos with AI voi ## Prerequisites -**No TTS engine ships by default.** Every engine is an optional peer dependency. Install one before running a pipeline: `npm i kokoro-js` (local, no API key) or `npm i openai` (cloud, needs `OPENAI_API_KEY`). Run `npx argo doctor` to see which engines are present and the exact install command for this project. +**No TTS engine ships by default.** Every engine is an optional peer dependency. Install one before running a pipeline: `npm i kokoro-js@1` (local, no API key) or `npm i openai` (cloud, needs `OPENAI_API_KEY`). Run `npx argo doctor` to see which engines are present and the exact install command for this project. 1. **`@argo-video/cli`** in `devDependencies` — install with `npm i -D @argo-video/cli` if missing 2. **`argo.config.mjs`** in project root — scaffold with `npx argo init` if missing (use `.mjs` to avoid ESM warnings) diff --git a/skills/argo-guide/references/tts-engines.md b/skills/argo-guide/references/tts-engines.md index a574f56..d962026 100644 --- a/skills/argo-guide/references/tts-engines.md +++ b/skills/argo-guide/references/tts-engines.md @@ -21,17 +21,17 @@ is added. `npx argo doctor` lists which are present. | Engine | Type | Install | Voices | |--------|------|---------|--------| -| `engines.kokoro()` | local | `npm i kokoro-js` | `af_heart`, `am_michael` | +| `engines.kokoro()` | local | `npm i kokoro-js@1` | `af_heart`, `am_michael` | | `engines.openai()` | cloud | `npm i openai` | `alloy`, `echo`, `fable`, `onyx`, `nova`, `shimmer` | | `engines.elevenlabs()` | cloud | `npm i @elevenlabs/elevenlabs-js` | ElevenLabs voice IDs | | `engines.gemini()` | cloud | `npm i @google/genai` | Gemini voice names | | `engines.sarvam()` | cloud | `npm i sarvamai` | `meera` + Indian language voices | | `engines.mlxAudio()` | local | `pip install mlx-audio` | model-dependent (Apple Silicon only) | -| `engines.transformers()` | local | `npm i @huggingface/transformers` | any HuggingFace `text-to-speech` model | +| `engines.transformers()` | local | `npm i @huggingface/transformers@3` | any HuggingFace `text-to-speech` model | Those commands assume a project-local Argo. For a global install add `-g`, and install Kokoro's two packages in one command so npm deduplicates the -ONNX runtime: `npm i -g kokoro-js @huggingface/transformers@^3`. For npx, +ONNX runtime: `npm i -g kokoro-js@1 @huggingface/transformers@3`. For npx, compose them: `npx -p @argo-video/cli -p openai -- argo pipeline `. Cloud engines read API keys from environment variables (`OPENAI_API_KEY`, `ELEVENLABS_API_KEY`, `GEMINI_API_KEY`, `SARVAM_API_KEY`) or accept `apiKey` in factory options. diff --git a/src/optional-deps.ts b/src/optional-deps.ts index 785b0aa..bd8f522 100644 --- a/src/optional-deps.ts +++ b/src/optional-deps.ts @@ -26,10 +26,14 @@ export type InstallMode = 'project' | 'global' | 'npx'; const PKG_NAME = '@argo-video/cli'; -/** `kokoro-js@^1.2.1` -> `kokoro-js`. Install lists carry version ranges for - * the user to paste; resolution and error text want the bare name. */ +/** `kokoro-js@1` -> `kokoro-js`. Install lists carry version ranges for the + * user to paste; resolution and error text want the bare name. + * + * Only the digit-led forms the specs actually use are recognised. A range + * written `@^1` would survive into the "bare" name and resolve to nothing, + * which is why the specs are tested for `^` and must not contain it. */ function bareName(specifier: string): string { - return specifier.replace(/@\^?[\d.].*$/, ''); + return specifier.replace(/@[\d.].*$/, ''); } /** Resolve a bare specifier as if from `dir`, or null if it does not resolve. @@ -58,29 +62,46 @@ export interface OptionalDepSpec { global: string[]; } +// The specs below pin a major, and write it `@3` rather than `@^3`. The two +// ranges are identical to npm (node-semver normalises both to +// `>=3.0.0 <4.0.0-0`), but `^` is a glob operator under zsh's `extendedglob`, +// where the pasted command dies with `no matches found` and never reaches npm. +// These strings exist to be pasted into a shell, so they avoid the character. +// The cloud SDKs further down need no pin: their peer ranges are open-ended, +// so whatever `latest` gives satisfies them. +// +// The pin itself is what keeps one ONNX runtime in the tree. `latest` is 4.x, +// so a bare `npm i @huggingface/transformers` next to an existing kokoro-js +// re-nests its 3.x copy underneath v4: ~765 MB against ~410 MB. A user who +// installs Kokoro and later enables `tts.transcribe` reaches that by following +// the hint printed here. Everything Argo asks of the package (`pipeline`, +// `AutoTokenizer`, `MusicgenForConditionalGeneration`, word-level Whisper +// timestamps) is verified on 3.8.1. Drop the pin once kokoro-js moves to v4. export const KOKORO_DEP: OptionalDepSpec = { feature: 'Kokoro local TTS', - project: ['kokoro-js'], + // Pinned to the major the peer range allows: an unpinned `npm i kokoro-js` + // would resolve to a future v2 and fail ERESOLVE against `^1.2.1`. + project: ['kokoro-js@1'], // kokoro-js keeps its own transformers copy private in a global tree. - global: ['kokoro-js', '@huggingface/transformers@^3'], + global: ['kokoro-js@1', '@huggingface/transformers@3'], }; export const TRANSFORMERS_DEP: OptionalDepSpec = { feature: 'local Transformers.js models', - project: ['@huggingface/transformers'], - global: ['@huggingface/transformers'], + project: ['@huggingface/transformers@3'], + global: ['@huggingface/transformers@3'], }; export const WHISPER_DEP: OptionalDepSpec = { feature: 'Whisper word-level transcription (`tts.transcribe`)', - project: ['@huggingface/transformers'], - global: ['@huggingface/transformers'], + project: ['@huggingface/transformers@3'], + global: ['@huggingface/transformers@3'], }; export const MUSICGEN_DEP: OptionalDepSpec = { feature: 'MusicGen background music generation', - project: ['@huggingface/transformers'], - global: ['@huggingface/transformers'], + project: ['@huggingface/transformers@3'], + global: ['@huggingface/transformers@3'], }; export const OPENAI_DEP: OptionalDepSpec = { @@ -135,13 +156,29 @@ export function detectInstallMode(): InstallMode { cachedMode = 'npx'; return cachedMode; } - const selfEntry = resolveFrom(selfDir, PKG_NAME); - if (selfEntry === null) { - // Running from a source checkout, not from an installed tree. + try { + const selfEntry = resolveFrom(selfDir, PKG_NAME); + if (selfEntry === null) { + // Running from a source checkout, not from an installed tree. + cachedMode = 'project'; + return cachedMode; + } + cachedMode = resolveFrom(process.cwd(), PKG_NAME) === selfEntry ? 'project' : 'global'; + } catch (err) { + // Resolving Argo's own name can fail without Argo being absent: an + // `exports` map with no condition matching the caller throws + // `ERR_PACKAGE_PATH_NOT_EXPORTED`, which this package shipped once (see + // Publishing in CLAUDE.md). Falling back beats propagating, because + // `doctor` calls this before anything else and must still print its + // table, and `installCommand` runs inside `importOptional`'s catch, where + // a throw here would replace the import failure the user needs to see. + // + // Same boundary as `isDepInstalled`: only resolution failures recover, + // and Node tags every one of those with a `code`. A bug in Argo must not + // be absorbed into a confident answer about where it is installed. + if (typeof (err as { code?: unknown } | null)?.code !== 'string') throw err; cachedMode = 'project'; - return cachedMode; } - cachedMode = resolveFrom(process.cwd(), PKG_NAME) === selfEntry ? 'project' : 'global'; return cachedMode; } @@ -211,7 +248,23 @@ export async function importOptional(load: () => Promise, spec: OptionalDe * * Only a genuine module-not-found means "absent". A corrupt manifest or a * broken `exports` map throws a different code and must not be reported as - * "not installed", or the user reinstalls a package that is already there. */ + * "not installed", or the user reinstalls a package that is already there. + * + * Reading this as "not known to be absent" is what makes it total. A probe + * can fail on its own: an interrupted `npm i` leaves a truncated + * `package.json` (`ERR_INVALID_PACKAGE_CONFIG`) and an `exports` map with no + * matching condition throws `ERR_PACKAGE_PATH_NOT_EXPORTED`. Neither may + * escape. `importOptional` calls this from inside a `catch`, where a throw + * would replace the real import failure, and `argo doctor` is the command a + * user runs precisely because their install is half-broken. */ export function isDepInstalled(spec: OptionalDepSpec): boolean { - return resolveFrom(dirname(fileURLToPath(import.meta.url)), bareName(spec.project[0])) !== null; + try { + return resolveFrom(dirname(fileURLToPath(import.meta.url)), bareName(spec.project[0])) !== null; + } catch (err) { + // Only resolution failures recover. Node tags every one of them with a + // `code`; a bug in Argo (a spec with an empty `project`, say) surfaces as + // a bare TypeError and must not be answered with "installed". + if (typeof (err as { code?: unknown } | null)?.code === 'string') return true; + throw err; + } } diff --git a/tests/optional-deps.test.ts b/tests/optional-deps.test.ts index 363044f..dd3570d 100644 --- a/tests/optional-deps.test.ts +++ b/tests/optional-deps.test.ts @@ -1,4 +1,7 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; +import { describe, it, expect, beforeEach, beforeAll, afterAll, vi } from 'vitest'; +import { mkdirSync, readdirSync, rmdirSync, rmSync, writeFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; import { installCommand, isModuleNotFound, @@ -8,12 +11,34 @@ import { detectInstallMode, resetInstallModeCache, KOKORO_DEP, - OPENAI_DEP, + TRANSFORMERS_DEP, WHISPER_DEP, + MUSICGEN_DEP, + OPENAI_DEP, + ELEVENLABS_DEP, + GEMINI_DEP, + SARVAM_DEP, type OptionalDepSpec, type InstallMode, } from '../src/optional-deps.js'; +/** `src/`, where `isDepInstalled` resolves from. A fixture placed under + * `src/node_modules` is therefore the first thing its probe finds. */ +const SRC_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'src'); + +/** Every spec Argo ships. Add new engines here so the shell-safety check + * below covers them. */ +const ALL_SPECS: OptionalDepSpec[] = [ + KOKORO_DEP, + TRANSFORMERS_DEP, + WHISPER_DEP, + MUSICGEN_DEP, + OPENAI_DEP, + ELEVENLABS_DEP, + GEMINI_DEP, + SARVAM_DEP, +]; + /** A spec pointing at a package that is deliberately not installed. */ const MISSING_DEP: OptionalDepSpec = { feature: 'a package that does not exist', @@ -32,9 +57,15 @@ describe('installCommand', () => { 'global Kokoro names both packages in one command', KOKORO_DEP, 'global', - 'npm i -g kokoro-js @huggingface/transformers@^3', + 'npm i -g kokoro-js@1 @huggingface/transformers@3', + ], + ['project Kokoro omits the hoisted transformers', KOKORO_DEP, 'project', 'npm i kokoro-js@1'], + [ + 'transformers specs pin the major kokoro-js shares', + WHISPER_DEP, + 'project', + 'npm i @huggingface/transformers@3', ], - ['project Kokoro omits the hoisted transformers', KOKORO_DEP, 'project', 'npm i kokoro-js'], [ 'npx composes packages onto the invocation', OPENAI_DEP, @@ -73,11 +104,23 @@ describe('missingDependencyError', () => { it('strips version ranges from the package name it reports', () => { const spec: OptionalDepSpec = { feature: 'test', - project: ['some-pkg@^3'], - global: ['some-pkg@^3'], + project: ['some-pkg@3'], + global: ['some-pkg@3'], }; expect(missingDependencyError(spec).message).toContain("'some-pkg'"); - expect(missingDependencyError(spec).message).not.toContain("'some-pkg@^3'"); + expect(missingDependencyError(spec).message).not.toContain("'some-pkg@3'"); + }); +}); + +describe('install commands are safe to paste', () => { + // `^` is a glob operator under zsh's `extendedglob`, where a pasted + // `npm i pkg@^3` dies with `no matches found` before npm ever runs. It also + // defeats `bareName`, which would leave `pkg@^3` as the name to resolve and + // report a present package as missing. Write ranges as `@3`. + it.each(ALL_SPECS)('$feature avoids shell metacharacters', (spec) => { + for (const entry of [...spec.project, ...spec.global]) { + expect(entry).not.toContain('^'); + } }); }); @@ -137,7 +180,50 @@ describe('isDepInstalled', () => { }); it('ignores a version range attached to the specifier', () => { - expect(isDepInstalled({ ...OPENAI_DEP, project: ['openai@^4'] })).toBe(true); + expect(isDepInstalled({ ...OPENAI_DEP, project: ['openai@4'] })).toBe(true); + }); + + it('still throws when the failure is a bug rather than a resolution', () => { + // An empty `project` makes `bareName` throw a bare TypeError. Recovering + // from that would hide the mistake behind a confident "installed". + expect(() => isDepInstalled({ feature: 'malformed', project: [], global: [] })).toThrow( + TypeError, + ); + }); + + describe('when the probe itself fails', () => { + // A package can be present and still refuse to resolve: an `exports` map + // with no condition matching the caller throws + // `ERR_PACKAGE_PATH_NOT_EXPORTED`, which is what an interrupted or + // mis-published install looks like. Answering "not installed" there would + // tell the user to reinstall something they already have, and throwing + // would take down `argo doctor`, the command they ran to diagnose it. + const FIXTURE = join(SRC_DIR, 'node_modules', 'argo-broken-exports-fixture'); + + beforeAll(() => { + mkdirSync(FIXTURE, { recursive: true }); + writeFileSync( + join(FIXTURE, 'package.json'), + JSON.stringify({ name: 'argo-broken-exports-fixture', exports: { './sub': './sub.js' } }), + ); + }); + // Remove only what was created. `src/node_modules` is covered by the + // repo's `node_modules/` gitignore, so deleting a copy this test did not + // make would be both silent and unrecoverable. + afterAll(() => { + rmSync(FIXTURE, { recursive: true, force: true }); + const parent = join(SRC_DIR, 'node_modules'); + if (readdirSync(parent).length === 0) rmdirSync(parent); + }); + + it('answers "not known to be absent" rather than throwing', () => { + const spec: OptionalDepSpec = { + feature: 'fixture', + project: ['argo-broken-exports-fixture'], + global: ['argo-broken-exports-fixture'], + }; + expect(isDepInstalled(spec)).toBe(true); + }); }); }); @@ -145,10 +231,19 @@ describe('detectInstallMode', () => { beforeEach(() => resetInstallModeCache()); it('reports project mode when running from the source checkout', () => { - // Tests run from src/, which is not inside any node_modules. + // Both probes resolve `@argo-video/cli` to this repo's own `dist/`, via + // Node's self-reference (the root manifest has both `name` and `exports`), + // so they match and the mode is project. Not the `selfEntry === null` + // branch, which a source checkout cannot reach for the same reason. expect(detectInstallMode()).toBe('project'); }); + // `detectInstallMode`'s own resolver-failure fallback has no test here: the + // self-reference above always wins for Argo's own name, so no fixture under + // `src/node_modules` can shadow it, and reproducing it needs a real + // installed consumer tree with a broken `exports` map. Verified by hand + // there instead: `argo doctor` prints its table rather than exiting 1. + it('caches the result instead of recomputing', () => { const first = detectInstallMode(); const spy = vi.spyOn(process, 'cwd'); From 5ff764c36b86024917ae48c849217169ea466e21 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:25:37 +0200 Subject: [PATCH 7/9] test: run eager-load guard on node 20 --- tests/optional-imports.test.ts | 82 +++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/tests/optional-imports.test.ts b/tests/optional-imports.test.ts index f6463bb..51124b4 100644 --- a/tests/optional-imports.test.ts +++ b/tests/optional-imports.test.ts @@ -1,14 +1,32 @@ import { describe, it, expect } from 'vitest'; -import { readFileSync, globSync } from 'node:fs'; +import { readFileSync, readdirSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, join, relative } from 'node:path'; const SRC = join(dirname(fileURLToPath(import.meta.url)), '..', 'src'); -/** Packages declared as optional peers in package.json. None may be reachable - * through a static import, or the whole install-footprint design collapses: - * a top-level import fails at module-link time and takes down every command, - * including ones that never touch TTS. */ +/** Every `.ts` under `dir`, recursively. + * + * Hand-rolled rather than `fs.globSync` (Node 22+) or `readdirSync`'s + * `recursive` option (Node 18.17/20.1+): this file is the only guard against + * an optional peer regressing to a static import, so it must not be the one + * thing in the suite that needs a newer Node than the package supports. On + * Node 20 `globSync` is undefined and the file died at collection, taking all + * of its assertions with it while CI stayed green on 24. */ +function sourceFiles(dir: string): string[] { + const found: string[] = []; + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, entry.name); + if (entry.isDirectory()) found.push(...sourceFiles(full)); + else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.d.ts')) found.push(full); + } + return found; +} + +/** Packages declared as optional peers in package.json. None may be loaded at + * module scope, or the whole install-footprint design collapses: a static + * import fails at link time and a top-level `require` at evaluation, either + * of which takes down every command, including ones that never touch TTS. */ const OPTIONAL_PACKAGES = [ 'kokoro-js', '@huggingface/transformers', @@ -18,31 +36,63 @@ const OPTIONAL_PACKAGES = [ 'sarvamai', ]; -/** `import x from 'pkg'` / `export * from 'pkg'` but NOT `import('pkg')`. - * The negative lookbehind on `(` is what separates static from dynamic. */ -function staticImportOf(pkg: string): RegExp { +/** Matches every form that loads the package eagerly: + * `import x from 'pkg'`, `export * from 'pkg'`, the bare side-effect + * `import 'pkg'`, and `require('pkg')`. Dynamic `import('pkg')` has no `from` + * and no quote directly after `import`, so it never matches, which is what + * lets `importOptional(() => import('pkg'), SPEC)` through. + * + * Subpaths count. `import { OpenAI } from 'openai/index.mjs'` links at load + * time exactly like the bare specifier does, and would otherwise slip past + * the one test standing between a regression and a broken install. + * + * `require.resolve('pkg')` is deliberately NOT matched: resolving asks + * whether a package is there without loading it, which is exactly what + * `isDepInstalled` does. */ +function eagerLoadOf(pkg: string): RegExp { const escaped = pkg.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - return new RegExp(`(? { +/** `createRequire(url)('pkg')` loads just as eagerly as `require('pkg')`. + * Rewriting the call to `require` lets one pattern cover both instead of + * growing `eagerLoadOf` into something nobody can read. + * + * Known gap: `const r = createRequire(url); r('pkg')` splits the call from + * the specifier across statements, and the binding can be named anything, so + * no line-based scan can see it. That two-step form is what `src/cli.ts` and + * `src/overlays/gsap-runtime.ts` already use, so treat this as defence in + * depth rather than proof. */ +const CREATE_REQUIRE = /createRequire\s*\([^)]*\)/g; + +/** `import type` / `export type` is erased before it reaches the runtime, so + * it cannot break an install that lacks the package. + * + * Stripped from the whole source rather than line by line: a wrapped type + * import leaves its `from` clause on a later line, which no per-line check + * can attribute back to the `type` keyword that opened the statement. */ +const TYPE_ONLY = /^[ \t]*(?:import|export)\s+type\b[\s\S]*?from\s*['"][^'"]*['"]/gm; + +describe('optional packages are never loaded at module scope', () => { // All six are devDependencies, so they resolve during tests. Nothing else in // the suite can notice a regression from `await import(x)` back to a // top-level `import x from`. This test is the only guard. - const files = globSync('**/*.ts', { cwd: SRC }) - .map((f) => join(SRC, f)) - .filter((f) => !f.endsWith('.d.ts')); + const files = sourceFiles(SRC); it('finds source files to scan', () => { expect(files.length).toBeGreaterThan(20); }); for (const pkg of OPTIONAL_PACKAGES) { - it(`no static import of ${pkg}`, () => { - const pattern = staticImportOf(pkg); + it(`no eager load of ${pkg}`, () => { + const pattern = eagerLoadOf(pkg); const offenders = files .filter((file) => { - const src = readFileSync(file, 'utf-8'); + const src = readFileSync(file, 'utf-8') + .replace(TYPE_ONLY, '') + .replace(CREATE_REQUIRE, 'require'); return src.split('\n').some((line) => { const code = line.replace(/\/\/.*$/, '').replace(/^\s*\*.*$/, ''); return pattern.test(code); From 4aeba521cb415e21af436b8beedf62d424a16201 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:25:44 +0200 Subject: [PATCH 8/9] build: declare node >=20 and test the floor --- .github/workflows/ci.yml | 11 +++++++++-- package.json | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e54a9b..8427f25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,16 +12,23 @@ env: jobs: unit: - name: Unit tests + name: Unit tests (node ${{ matrix.node }}) runs-on: ubuntu-latest # A stalled apt/playwright install should fail fast, not burn the full # 6h default job budget. The unit suite itself runs in seconds. timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + # Both ends of the supported range. Testing only the top hid a test + # that used a Node 22+ API and silently collected zero assertions + # everywhere below it. + node: [20, 24] steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: - node-version: 24 + node-version: ${{ matrix.node }} # ffmpeg is needed for boundary-frame extraction and shader pre-render. - run: sudo apt-get update && sudo apt-get install -y ffmpeg - run: npm install diff --git a/package.json b/package.json index 7cc1a5e..d9296f8 100644 --- a/package.json +++ b/package.json @@ -87,5 +87,8 @@ "sarvamai": { "optional": true } + }, + "engines": { + "node": ">=20" } } From 83cde2ad4fd318c2a19a24ac1e5460396e1e0af8 Mon Sep 17 00:00:00 2001 From: Jonathan Yang <14588641+Joilence@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:25:44 +0200 Subject: [PATCH 9/9] style(music): group import with locals --- src/music/musicgen.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/music/musicgen.ts b/src/music/musicgen.ts index e59c9eb..148f585 100644 --- a/src/music/musicgen.ts +++ b/src/music/musicgen.ts @@ -4,9 +4,9 @@ */ import crypto from 'node:crypto'; -import { importOptional, MUSICGEN_DEP } from '../optional-deps.js'; import fs from 'node:fs'; import path from 'node:path'; +import { importOptional, MUSICGEN_DEP } from '../optional-deps.js'; import { createWavBuffer } from '../tts/engine.js'; export interface MusicGenOptions {