@tryhamster/gerbil 1.0.0-rc.0 → 1.0.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -14
- package/dist/auto-update-S9s5-g0C.mjs +3 -0
- package/dist/browser/index.d.ts +1009 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +2492 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/{chrome-backend-C5Un08O4.mjs → chrome-backend-CORwaIyC.mjs} +514 -73
- package/dist/chrome-backend-CORwaIyC.mjs.map +1 -0
- package/dist/{chrome-backend-CtwPENIW.mjs → chrome-backend-DIKYoWj-.mjs} +1 -1
- package/dist/cli.mjs +3359 -647
- package/dist/cli.mjs.map +1 -1
- package/dist/frameworks/express.d.mts +1 -1
- package/dist/frameworks/express.mjs +3 -4
- package/dist/frameworks/express.mjs.map +1 -1
- package/dist/frameworks/fastify.d.mts +1 -1
- package/dist/frameworks/fastify.mjs +2 -3
- package/dist/frameworks/fastify.mjs.map +1 -1
- package/dist/frameworks/hono.d.mts +1 -1
- package/dist/frameworks/hono.mjs +2 -3
- package/dist/frameworks/hono.mjs.map +1 -1
- package/dist/frameworks/next.d.mts +2 -2
- package/dist/frameworks/next.mjs +2 -3
- package/dist/frameworks/next.mjs.map +1 -1
- package/dist/frameworks/react.d.mts +1 -1
- package/dist/frameworks/trpc.d.mts +1 -1
- package/dist/frameworks/trpc.mjs +2 -3
- package/dist/frameworks/trpc.mjs.map +1 -1
- package/dist/gerbil-DJGqq7BX.mjs +4 -0
- package/dist/gerbil-DoDGHe6Z.mjs +1631 -0
- package/dist/gerbil-DoDGHe6Z.mjs.map +1 -0
- package/dist/gerbil-qOTe1nl2.d.mts +431 -0
- package/dist/gerbil-qOTe1nl2.d.mts.map +1 -0
- package/dist/index.d.mts +411 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -6
- package/dist/index.mjs.map +1 -1
- package/dist/integrations/ai-sdk.d.mts +122 -4
- package/dist/integrations/ai-sdk.d.mts.map +1 -1
- package/dist/integrations/ai-sdk.mjs +238 -11
- package/dist/integrations/ai-sdk.mjs.map +1 -1
- package/dist/integrations/langchain.d.mts +132 -2
- package/dist/integrations/langchain.d.mts.map +1 -1
- package/dist/integrations/langchain.mjs +175 -8
- package/dist/integrations/langchain.mjs.map +1 -1
- package/dist/integrations/llamaindex.d.mts +1 -1
- package/dist/integrations/llamaindex.mjs +2 -3
- package/dist/integrations/llamaindex.mjs.map +1 -1
- package/dist/integrations/mcp-client.mjs +4 -4
- package/dist/integrations/mcp-client.mjs.map +1 -1
- package/dist/integrations/mcp.d.mts +2 -2
- package/dist/integrations/mcp.d.mts.map +1 -1
- package/dist/integrations/mcp.mjs +5 -6
- package/dist/kokoro-BNTb6egA.mjs +20210 -0
- package/dist/kokoro-BNTb6egA.mjs.map +1 -0
- package/dist/kokoro-CMOGDSgT.js +20212 -0
- package/dist/kokoro-CMOGDSgT.js.map +1 -0
- package/dist/{mcp-R8kRLIKb.mjs → mcp-kzDDWIoS.mjs} +10 -37
- package/dist/mcp-kzDDWIoS.mjs.map +1 -0
- package/dist/microphone-DaMZFRuR.mjs +3 -0
- package/dist/{one-liner-BUQR0nqq.mjs → one-liner-DxnNs_JK.mjs} +2 -2
- package/dist/{one-liner-BUQR0nqq.mjs.map → one-liner-DxnNs_JK.mjs.map} +1 -1
- package/dist/repl-DGUw4fCc.mjs +9 -0
- package/dist/skills/index.d.mts +305 -14
- package/dist/skills/index.d.mts.map +1 -1
- package/dist/skills/index.mjs +5 -6
- package/dist/skills-DulrOPeP.mjs +1435 -0
- package/dist/skills-DulrOPeP.mjs.map +1 -0
- package/dist/stt-1WIefHwc.mjs +3 -0
- package/dist/stt-CG_7KB_0.mjs +434 -0
- package/dist/stt-CG_7KB_0.mjs.map +1 -0
- package/dist/stt-Dne6SENv.js +434 -0
- package/dist/stt-Dne6SENv.js.map +1 -0
- package/dist/{tools-BsiEE6f2.mjs → tools-Bi1P7Xoy.mjs} +6 -7
- package/dist/{tools-BsiEE6f2.mjs.map → tools-Bi1P7Xoy.mjs.map} +1 -1
- package/dist/transformers.web-DiD1gTwk.js +44695 -0
- package/dist/transformers.web-DiD1gTwk.js.map +1 -0
- package/dist/transformers.web-u34VxRFM.js +3 -0
- package/dist/tts-B1pZMlDv.mjs +3 -0
- package/dist/tts-C2FzKuSx.js +725 -0
- package/dist/tts-C2FzKuSx.js.map +1 -0
- package/dist/tts-CyHhcLtN.mjs +731 -0
- package/dist/tts-CyHhcLtN.mjs.map +1 -0
- package/dist/types-CiTc7ez3.d.mts +353 -0
- package/dist/types-CiTc7ez3.d.mts.map +1 -0
- package/dist/{utils-7vXqtq2Q.mjs → utils-CZBZ8dgR.mjs} +1 -1
- package/dist/{utils-7vXqtq2Q.mjs.map → utils-CZBZ8dgR.mjs.map} +1 -1
- package/docs/ai-sdk.md +137 -21
- package/docs/browser.md +241 -2
- package/docs/memory.md +72 -0
- package/docs/stt.md +494 -0
- package/docs/tts.md +569 -0
- package/docs/vision.md +396 -0
- package/package.json +21 -22
- package/dist/auto-update-BbNHbSU1.mjs +0 -3
- package/dist/browser/index.d.mts +0 -262
- package/dist/browser/index.d.mts.map +0 -1
- package/dist/browser/index.mjs +0 -755
- package/dist/browser/index.mjs.map +0 -1
- package/dist/chrome-backend-C5Un08O4.mjs.map +0 -1
- package/dist/gerbil-BfnsFWRE.mjs +0 -644
- package/dist/gerbil-BfnsFWRE.mjs.map +0 -1
- package/dist/gerbil-BjW-z7Fq.mjs +0 -5
- package/dist/gerbil-DZ1k3ChC.d.mts +0 -138
- package/dist/gerbil-DZ1k3ChC.d.mts.map +0 -1
- package/dist/mcp-R8kRLIKb.mjs.map +0 -1
- package/dist/models-DKULvhOr.mjs +0 -136
- package/dist/models-DKULvhOr.mjs.map +0 -1
- package/dist/models-De2-_GmQ.d.mts +0 -22
- package/dist/models-De2-_GmQ.d.mts.map +0 -1
- package/dist/skills-D3CEpgDc.mjs +0 -630
- package/dist/skills-D3CEpgDc.mjs.map +0 -1
- package/dist/types-BS1N92Jt.d.mts +0 -183
- package/dist/types-BS1N92Jt.d.mts.map +0 -1
- /package/dist/{chunk-Ct1HF2bE.mjs → chunk-CkXuGtQK.mjs} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-CyHhcLtN.mjs","names":["KOKORO_VOICES: VoiceInfo[]","SUPERTONIC_VOICES: VoiceInfo[]","TTS_MODELS: Record<string, TTSModelConfig>","dtype: \"fp32\" | \"fp16\" | \"q8\" | \"q4\" | \"q4f16\"","allAudio: Float32Array[]","chunk: AudioChunk"],"sources":["../src/core/tts.ts"],"sourcesContent":["/**\n * Text-to-Speech with Kokoro-82M\n *\n * Provides local TTS using the Kokoro-82M model with multiple voice options.\n * Uses kokoro-js for proper phoneme conversion (G2P) and audio generation.\n * Supports streaming audio generation and works in both Node.js and browser.\n *\n * @example\n * ```ts\n * const tts = new KokoroTTS();\n * await tts.load({ onProgress: (p) => console.log(p.status) });\n *\n * // List available voices\n * const voices = tts.listVoices();\n *\n * // Generate audio\n * const result = await tts.speak(\"Hello world\", { voice: \"af_bella\" });\n * // result.audio = Float32Array, result.sampleRate = 24000\n *\n * // Stream audio chunks\n * for await (const chunk of tts.speakStream(\"Long text...\")) {\n * playAudioChunk(chunk);\n * }\n * ```\n */\n\nimport type {\n AudioChunk,\n LoadTTSOptions,\n SpeakOptions,\n SpeakResult,\n TTSModelConfig,\n VoiceInfo,\n} from \"./types.js\";\n\n// Regex for sentence splitting (defined at module level for performance)\nconst SENTENCE_SPLIT_REGEX = /(?<=[.!?])\\s+/;\n\n// ============================================\n// Voice Registry\n// ============================================\n\n/**\n * Kokoro voice definitions\n * Voice IDs follow pattern: {language}{gender}_{name}\n * - a = American English\n * - b = British English\n * - f = female, m = male\n */\nexport const KOKORO_VOICES: VoiceInfo[] = [\n // American English - Female (ordered by quality)\n {\n id: \"af_heart\",\n name: \"Heart\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female, highest quality voice (Grade A)\",\n embeddingFile: \"voices/af_heart.bin\",\n },\n {\n id: \"af_bella\",\n name: \"Bella\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female, warm and friendly (Grade A-)\",\n embeddingFile: \"voices/af_bella.bin\",\n },\n {\n id: \"af_nicole\",\n name: \"Nicole\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female, soft and gentle (Grade B-)\",\n embeddingFile: \"voices/af_nicole.bin\",\n },\n {\n id: \"af_sarah\",\n name: \"Sarah\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female, clear and professional (Grade C+)\",\n embeddingFile: \"voices/af_sarah.bin\",\n },\n {\n id: \"af_sky\",\n name: \"Sky\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female, young and energetic (Grade C-)\",\n embeddingFile: \"voices/af_sky.bin\",\n },\n {\n id: \"af_alloy\",\n name: \"Alloy\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade C)\",\n embeddingFile: \"voices/af_alloy.bin\",\n },\n {\n id: \"af_aoede\",\n name: \"Aoede\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade C+)\",\n embeddingFile: \"voices/af_aoede.bin\",\n },\n {\n id: \"af_kore\",\n name: \"Kore\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade C+)\",\n embeddingFile: \"voices/af_kore.bin\",\n },\n {\n id: \"af_nova\",\n name: \"Nova\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade C)\",\n embeddingFile: \"voices/af_nova.bin\",\n },\n {\n id: \"af_river\",\n name: \"River\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade D)\",\n embeddingFile: \"voices/af_river.bin\",\n },\n {\n id: \"af_jessica\",\n name: \"Jessica\",\n gender: \"female\",\n language: \"en-us\",\n description: \"American female (Grade D)\",\n embeddingFile: \"voices/af_jessica.bin\",\n },\n // American English - Male\n {\n id: \"am_fenrir\",\n name: \"Fenrir\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male, best quality (Grade C+)\",\n embeddingFile: \"voices/am_fenrir.bin\",\n },\n {\n id: \"am_michael\",\n name: \"Michael\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male, warm and friendly (Grade C+)\",\n embeddingFile: \"voices/am_michael.bin\",\n },\n {\n id: \"am_puck\",\n name: \"Puck\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male (Grade C+)\",\n embeddingFile: \"voices/am_puck.bin\",\n },\n {\n id: \"am_adam\",\n name: \"Adam\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male, deep voice (Grade F+)\",\n embeddingFile: \"voices/am_adam.bin\",\n },\n {\n id: \"am_echo\",\n name: \"Echo\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male (Grade D)\",\n embeddingFile: \"voices/am_echo.bin\",\n },\n {\n id: \"am_eric\",\n name: \"Eric\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male (Grade D)\",\n embeddingFile: \"voices/am_eric.bin\",\n },\n {\n id: \"am_liam\",\n name: \"Liam\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male (Grade D)\",\n embeddingFile: \"voices/am_liam.bin\",\n },\n {\n id: \"am_onyx\",\n name: \"Onyx\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male (Grade D)\",\n embeddingFile: \"voices/am_onyx.bin\",\n },\n {\n id: \"am_santa\",\n name: \"Santa\",\n gender: \"male\",\n language: \"en-us\",\n description: \"American male, festive (Grade D-)\",\n embeddingFile: \"voices/am_santa.bin\",\n },\n // British English - Female\n {\n id: \"bf_emma\",\n name: \"Emma\",\n gender: \"female\",\n language: \"en-gb\",\n description: \"British female, elegant and clear (Grade B-)\",\n embeddingFile: \"voices/bf_emma.bin\",\n },\n {\n id: \"bf_isabella\",\n name: \"Isabella\",\n gender: \"female\",\n language: \"en-gb\",\n description: \"British female, sophisticated (Grade C)\",\n embeddingFile: \"voices/bf_isabella.bin\",\n },\n {\n id: \"bf_alice\",\n name: \"Alice\",\n gender: \"female\",\n language: \"en-gb\",\n description: \"British female (Grade D)\",\n embeddingFile: \"voices/bf_alice.bin\",\n },\n {\n id: \"bf_lily\",\n name: \"Lily\",\n gender: \"female\",\n language: \"en-gb\",\n description: \"British female (Grade D)\",\n embeddingFile: \"voices/bf_lily.bin\",\n },\n // British English - Male\n {\n id: \"bm_george\",\n name: \"George\",\n gender: \"male\",\n language: \"en-gb\",\n description: \"British male, distinguished (Grade C)\",\n embeddingFile: \"voices/bm_george.bin\",\n },\n {\n id: \"bm_fable\",\n name: \"Fable\",\n gender: \"male\",\n language: \"en-gb\",\n description: \"British male (Grade C)\",\n embeddingFile: \"voices/bm_fable.bin\",\n },\n {\n id: \"bm_lewis\",\n name: \"Lewis\",\n gender: \"male\",\n language: \"en-gb\",\n description: \"British male, friendly (Grade D+)\",\n embeddingFile: \"voices/bm_lewis.bin\",\n },\n {\n id: \"bm_daniel\",\n name: \"Daniel\",\n gender: \"male\",\n language: \"en-gb\",\n description: \"British male (Grade D)\",\n embeddingFile: \"voices/bm_daniel.bin\",\n },\n];\n\n// ============================================\n// Supertonic Voice Registry\n// ============================================\n\n/**\n * Supertonic voice definitions\n * 4 built-in voices: F1, F2 (female), M1, M2 (male)\n */\nexport const SUPERTONIC_VOICES: VoiceInfo[] = [\n {\n id: \"F1\",\n name: \"Female 1\",\n gender: \"female\",\n language: \"en\",\n description: \"Female voice 1 - Clear and natural\",\n embeddingFile: \"voices/F1.bin\",\n },\n {\n id: \"F2\",\n name: \"Female 2\",\n gender: \"female\",\n language: \"en\",\n description: \"Female voice 2 - Warm and expressive\",\n embeddingFile: \"voices/F2.bin\",\n },\n {\n id: \"M1\",\n name: \"Male 1\",\n gender: \"male\",\n language: \"en\",\n description: \"Male voice 1 - Deep and confident\",\n embeddingFile: \"voices/M1.bin\",\n },\n {\n id: \"M2\",\n name: \"Male 2\",\n gender: \"male\",\n language: \"en\",\n description: \"Male voice 2 - Friendly and casual\",\n embeddingFile: \"voices/M2.bin\",\n },\n];\n\n// ============================================\n// TTS Model Registry\n// ============================================\n\nexport const TTS_MODELS: Record<string, TTSModelConfig> = {\n \"kokoro-82m\": {\n id: \"kokoro-82m\",\n repo: \"onnx-community/Kokoro-82M-v1.0-ONNX\",\n description: \"Kokoro 82M - High-quality multilingual TTS\",\n size: \"~330MB\",\n sampleRate: 24000,\n voices: KOKORO_VOICES,\n defaultVoice: \"af_heart\",\n languages: [\"en-us\", \"en-gb\"],\n },\n \"supertonic-66m\": {\n id: \"supertonic-66m\",\n repo: \"onnx-community/Supertonic-TTS-ONNX\",\n description: \"Supertonic 66M - Fast on-device TTS (167x realtime)\",\n size: \"~250MB\",\n sampleRate: 44100,\n voices: SUPERTONIC_VOICES,\n defaultVoice: \"F1\",\n languages: [\"en\"],\n },\n};\n\n/**\n * Get TTS model config by ID\n */\nexport function getTTSModelConfig(modelId: string): TTSModelConfig | null {\n return TTS_MODELS[modelId] || null;\n}\n\n/**\n * List all available TTS models\n */\nexport function listTTSModels(): TTSModelConfig[] {\n return Object.values(TTS_MODELS);\n}\n\n// ============================================\n// Kokoro TTS Class (wraps kokoro-js)\n// ============================================\n\n// kokoro-js types\ninterface KokoroJSAudio {\n audio: Float32Array;\n sampling_rate: number;\n}\n\ninterface KokoroJSInstance {\n generate(text: string, options?: { voice?: string; speed?: number }): Promise<KokoroJSAudio>;\n list_voices(): Array<{\n name: string;\n language: string;\n gender: string;\n traits: string;\n targetQuality: string;\n overallGrade: string;\n }>;\n}\n\n/**\n * Kokoro TTS - Local text-to-speech with voice selection\n *\n * Uses kokoro-js (official Kokoro library by xenova) for high-quality speech synthesis.\n * Includes proper G2P (grapheme-to-phoneme) conversion for accurate pronunciation.\n */\nexport class KokoroTTS {\n private kokoroInstance: KokoroJSInstance | null = null;\n private modelConfig: TTSModelConfig;\n private loadPromise: Promise<void> | null = null;\n private _isLoaded = false;\n private _deviceMode: \"webgpu\" | \"cpu\" = \"cpu\";\n\n constructor(modelId = \"kokoro-82m\") {\n const config = getTTSModelConfig(modelId);\n if (!config) {\n throw new Error(\n `Unknown TTS model: ${modelId}. Available: ${Object.keys(TTS_MODELS).join(\", \")}`,\n );\n }\n this.modelConfig = config;\n }\n\n // ============================================\n // Model Loading\n // ============================================\n\n /**\n * Load the TTS model\n *\n * @example\n * ```ts\n * const tts = new KokoroTTS();\n * await tts.load({\n * onProgress: (p) => console.log(p.status, p.progress),\n * device: \"webgpu\",\n * });\n * ```\n */\n async load(options: LoadTTSOptions = {}): Promise<void> {\n if (this._isLoaded) {\n return;\n }\n\n // Prevent duplicate loads\n if (this.loadPromise) {\n return this.loadPromise;\n }\n\n this.loadPromise = this._load(options);\n await this.loadPromise;\n }\n\n private async _load(options: LoadTTSOptions = {}): Promise<void> {\n const { onProgress, device = \"auto\" } = options;\n\n onProgress?.({ status: `Loading TTS model (${this.modelConfig.id})...` });\n\n try {\n // Dynamically import kokoro-js\n // tsdown handles resolution: Node.js = external, Browser = bundled\n const kokoroModule = await import(\"kokoro-js\");\n const { KokoroTTS: KokoroJS } = kokoroModule;\n\n // Determine device/dtype\n const isBrowser = typeof window !== \"undefined\";\n let dtype: \"fp32\" | \"fp16\" | \"q8\" | \"q4\" | \"q4f16\" = \"fp32\";\n\n if (device === \"webgpu\" || (device === \"auto\" && isBrowser && \"gpu\" in navigator)) {\n dtype = \"fp16\";\n this._deviceMode = \"webgpu\";\n } else {\n dtype = \"fp32\";\n this._deviceMode = \"cpu\";\n }\n\n onProgress?.({ status: `Loading model with ${dtype} precision...` });\n\n // Load the model using kokoro-js\n // kokoro-js handles:\n // - Model loading with proper quantization\n // - Phoneme tokenization (G2P) via phonemizer\n // - Voice embeddings\n this.kokoroInstance = (await KokoroJS.from_pretrained(this.modelConfig.repo, {\n dtype,\n progress_callback: (progress: any) => {\n if (progress.status === \"progress\" && progress.file) {\n onProgress?.({\n status: `Downloading ${progress.file}`,\n progress: Math.round(progress.progress || 0),\n file: progress.file,\n });\n } else if (progress.status === \"ready\") {\n onProgress?.({ status: \"Model ready\" });\n }\n },\n })) as unknown as KokoroJSInstance;\n\n this._isLoaded = true;\n onProgress?.({ status: `Ready (${this._deviceMode.toUpperCase()})!` });\n } catch (error) {\n this.loadPromise = null;\n throw error;\n }\n }\n\n /**\n * Ensure model is loaded (lazy loading)\n */\n async ensureLoaded(options?: LoadTTSOptions): Promise<void> {\n if (!this._isLoaded) {\n await this.load(options);\n }\n }\n\n // ============================================\n // Voice Management\n // ============================================\n\n /**\n * Get list of available voices\n *\n * @example\n * ```ts\n * const voices = tts.listVoices();\n * // [{ id: \"af_heart\", name: \"Heart\", gender: \"female\", ... }, ...]\n * ```\n */\n listVoices(): VoiceInfo[] {\n return [...this.modelConfig.voices];\n }\n\n /**\n * Get a specific voice by ID\n */\n getVoice(voiceId: string): VoiceInfo | null {\n return this.modelConfig.voices.find((v) => v.id === voiceId) || null;\n }\n\n /**\n * Get voices by gender\n */\n getVoicesByGender(gender: \"male\" | \"female\"): VoiceInfo[] {\n return this.modelConfig.voices.filter((v) => v.gender === gender);\n }\n\n /**\n * Get voices by language\n */\n getVoicesByLanguage(language: string): VoiceInfo[] {\n return this.modelConfig.voices.filter(\n (v) => v.language === language || v.language.startsWith(language),\n );\n }\n\n // ============================================\n // Speech Generation\n // ============================================\n\n /**\n * Generate speech from text\n *\n * @example\n * ```ts\n * const result = await tts.speak(\"Hello world\", {\n * voice: \"af_heart\",\n * speed: 1.0,\n * });\n *\n * // Play in browser\n * const audioContext = new AudioContext();\n * const buffer = audioContext.createBuffer(1, result.audio.length, result.sampleRate);\n * buffer.copyToChannel(result.audio, 0);\n * const source = audioContext.createBufferSource();\n * source.buffer = buffer;\n * source.connect(audioContext.destination);\n * source.start();\n * ```\n */\n async speak(text: string, options: SpeakOptions = {}): Promise<SpeakResult> {\n await this.ensureLoaded({ onProgress: options.onProgress });\n\n const { voice = this.modelConfig.defaultVoice, speed = 1.0 } = options;\n\n // Validate voice exists in our registry\n const voiceInfo = this.getVoice(voice);\n if (!voiceInfo) {\n throw new Error(`Unknown voice: ${voice}. Use listVoices() to see available options.`);\n }\n\n if (!this.kokoroInstance) {\n throw new Error(\"Model not loaded\");\n }\n\n const startTime = performance.now();\n\n // Generate audio using kokoro-js\n const result = await this.kokoroInstance.generate(text, {\n voice,\n speed,\n });\n\n const totalTime = performance.now() - startTime;\n\n return {\n audio: result.audio,\n sampleRate: result.sampling_rate,\n duration: result.audio.length / result.sampling_rate,\n voice,\n totalTime,\n };\n }\n\n /**\n * Stream speech generation (yields audio chunks as they're generated)\n *\n * @example\n * ```ts\n * for await (const chunk of tts.speakStream(\"Long text...\")) {\n * // chunk.samples = Float32Array\n * // chunk.sampleRate = 24000\n * // chunk.isFinal = boolean\n * playChunk(chunk);\n * }\n * ```\n */\n async *speakStream(\n text: string,\n options: SpeakOptions = {},\n ): AsyncGenerator<AudioChunk, SpeakResult, unknown> {\n await this.ensureLoaded({ onProgress: options.onProgress });\n\n const { voice = this.modelConfig.defaultVoice, speed = 1.0 } = options;\n\n // Validate voice\n const voiceInfo = this.getVoice(voice);\n if (!voiceInfo) {\n throw new Error(`Unknown voice: ${voice}. Use listVoices() to see available options.`);\n }\n\n if (!this.kokoroInstance) {\n throw new Error(\"Model not loaded\");\n }\n\n const startTime = performance.now();\n\n // Split text into sentences for streaming\n const sentences = this.splitIntoSentences(text);\n const allAudio: Float32Array[] = [];\n let chunkIndex = 0;\n let sampleRate = this.modelConfig.sampleRate;\n\n for (let i = 0; i < sentences.length; i++) {\n const sentence = sentences[i];\n if (!sentence.trim()) {\n continue;\n }\n\n const result = await this.kokoroInstance.generate(sentence, {\n voice,\n speed,\n });\n\n sampleRate = result.sampling_rate;\n allAudio.push(result.audio);\n\n const chunk: AudioChunk = {\n samples: result.audio,\n sampleRate: result.sampling_rate,\n index: chunkIndex++,\n isFinal: i === sentences.length - 1,\n };\n\n yield chunk;\n options.onAudioChunk?.(chunk);\n }\n\n // Concatenate all audio\n const totalLength = allAudio.reduce((sum, arr) => sum + arr.length, 0);\n const fullAudio = new Float32Array(totalLength);\n let offset = 0;\n for (const chunk of allAudio) {\n fullAudio.set(chunk, offset);\n offset += chunk.length;\n }\n\n const totalTime = performance.now() - startTime;\n\n return {\n audio: fullAudio,\n sampleRate,\n duration: fullAudio.length / sampleRate,\n voice,\n totalTime,\n };\n }\n\n /**\n * Split text into sentences for streaming\n */\n private splitIntoSentences(text: string): string[] {\n // Split on sentence boundaries while preserving the delimiters\n return text.split(SENTENCE_SPLIT_REGEX).filter((s) => s.trim());\n }\n\n // ============================================\n // Status & Info\n // ============================================\n\n /**\n * Check if model is loaded\n */\n isLoaded(): boolean {\n return this._isLoaded;\n }\n\n /**\n * Get current device mode\n */\n getDeviceMode(): \"webgpu\" | \"cpu\" {\n return this._deviceMode;\n }\n\n /**\n * Get model configuration\n */\n getModelInfo(): TTSModelConfig {\n return { ...this.modelConfig };\n }\n\n /**\n * Get sample rate\n */\n getSampleRate(): number {\n return this.modelConfig.sampleRate;\n }\n\n // ============================================\n // Cleanup\n // ============================================\n\n /**\n * Dispose of resources\n */\n async dispose(): Promise<void> {\n // kokoro-js doesn't expose a dispose method currently\n // but we clear our reference\n this.kokoroInstance = null;\n this._isLoaded = false;\n this.loadPromise = null;\n }\n}\n\n// ============================================\n// Supertonic TTS Class (uses transformers.js)\n// ============================================\n\n/**\n * Supertonic TTS - Fast on-device text-to-speech\n *\n * Uses transformers.js with the Supertonic-TTS-ONNX model.\n * Generates speech at 167x realtime with 66M parameters.\n * Outputs at 44100 Hz sample rate.\n */\nexport class SupertonicTTS {\n private pipeline: any = null;\n private modelConfig: TTSModelConfig;\n private loadPromise: Promise<void> | null = null;\n private _isLoaded = false;\n private _deviceMode: \"webgpu\" | \"cpu\" = \"cpu\";\n private voiceEmbeddings: Map<string, Float32Array> = new Map();\n\n constructor(modelId = \"supertonic-66m\") {\n const config = getTTSModelConfig(modelId);\n if (!config) {\n throw new Error(\n `Unknown TTS model: ${modelId}. Available: ${Object.keys(TTS_MODELS).join(\", \")}`,\n );\n }\n this.modelConfig = config;\n }\n\n /**\n * Load the TTS model\n */\n async load(options: LoadTTSOptions = {}): Promise<void> {\n if (this._isLoaded) {\n return;\n }\n\n if (this.loadPromise) {\n return this.loadPromise;\n }\n\n this.loadPromise = this._load(options);\n await this.loadPromise;\n }\n\n private async _load(options: LoadTTSOptions = {}): Promise<void> {\n const { onProgress, device = \"auto\" } = options;\n\n onProgress?.({ status: `Loading TTS model (${this.modelConfig.id})...` });\n\n try {\n // Determine device\n const isBrowser = typeof window !== \"undefined\";\n\n // Dynamically import transformers.js\n // tsdown handles resolution: Node.js = external, Browser = bundled\n const { pipeline, env } = await import(\"@huggingface/transformers\");\n\n // Configure WASM paths for browser (load from CDN, not bundled)\n if (isBrowser && env.backends?.onnx?.wasm) {\n env.backends.onnx.wasm.wasmPaths =\n \"https://cdn.jsdelivr.net/npm/onnxruntime-web@1.21.0/dist/\";\n }\n\n if (device === \"webgpu\" || (device === \"auto\" && isBrowser && \"gpu\" in navigator)) {\n this._deviceMode = \"webgpu\";\n } else {\n this._deviceMode = \"cpu\";\n }\n\n onProgress?.({ status: `Loading Supertonic model...` });\n\n // Create TTS pipeline\n this.pipeline = await pipeline(\"text-to-speech\", this.modelConfig.repo, {\n dtype: \"fp32\", // Supertonic works best with fp32\n device: this._deviceMode,\n progress_callback: (progress: any) => {\n if (progress.status === \"progress\" && progress.file) {\n onProgress?.({\n status: `Downloading ${progress.file}`,\n progress: Math.round(progress.progress || 0),\n file: progress.file,\n });\n }\n },\n });\n\n // Load voice embeddings\n onProgress?.({ status: \"Loading voice embeddings...\" });\n await this.loadVoiceEmbeddings();\n\n this._isLoaded = true;\n onProgress?.({ status: `Ready (${this._deviceMode.toUpperCase()})!` });\n } catch (error) {\n this.loadPromise = null;\n throw error;\n }\n }\n\n /**\n * Load speaker embeddings for all voices\n * Supertonic uses 101x128 = 12,928 floats per voice\n */\n private async loadVoiceEmbeddings(): Promise<void> {\n // In browser, we'd fetch from HuggingFace Hub\n // In Node.js, we'd load from cache\n // For now, we'll lazy-load embeddings when needed\n // The pipeline handles this internally when we pass speaker_embeddings\n }\n\n async ensureLoaded(options?: LoadTTSOptions): Promise<void> {\n if (!this._isLoaded) {\n await this.load(options);\n }\n }\n\n listVoices(): VoiceInfo[] {\n return [...this.modelConfig.voices];\n }\n\n getVoice(voiceId: string): VoiceInfo | null {\n return this.modelConfig.voices.find((v) => v.id === voiceId) || null;\n }\n\n getVoicesByGender(gender: \"male\" | \"female\"): VoiceInfo[] {\n return this.modelConfig.voices.filter((v) => v.gender === gender);\n }\n\n /**\n * Generate speech from text\n */\n async speak(text: string, options: SpeakOptions = {}): Promise<SpeakResult> {\n await this.ensureLoaded({ onProgress: options.onProgress });\n\n const { voice = this.modelConfig.defaultVoice } = options;\n\n // Validate voice\n const voiceInfo = this.getVoice(voice);\n if (!voiceInfo) {\n throw new Error(`Unknown voice: ${voice}. Use listVoices() to see available options.`);\n }\n\n if (!this.pipeline) {\n throw new Error(\"Model not loaded\");\n }\n\n const startTime = performance.now();\n\n // Get or create speaker embedding\n // Supertonic expects [101, 128] = 12,928 floats\n let speakerEmbedding = this.voiceEmbeddings.get(voice);\n if (!speakerEmbedding) {\n // Load from HuggingFace Hub via fetch\n try {\n const voiceUrl = `https://huggingface.co/${this.modelConfig.repo}/resolve/main/voices/${voice}.bin`;\n const response = await fetch(voiceUrl);\n if (response.ok) {\n const buffer = await response.arrayBuffer();\n speakerEmbedding = new Float32Array(buffer);\n this.voiceEmbeddings.set(voice, speakerEmbedding);\n } else {\n throw new Error(`Failed to load voice: ${response.status}`);\n }\n } catch {\n // Fallback: create neutral embedding (not ideal but works)\n speakerEmbedding = new Float32Array(101 * 128).fill(0.1);\n this.voiceEmbeddings.set(voice, speakerEmbedding);\n }\n }\n\n // Generate audio\n const result = await this.pipeline(text, {\n speaker_embeddings: speakerEmbedding,\n });\n\n const totalTime = performance.now() - startTime;\n const audio = result.audio as Float32Array;\n const sampleRate = result.sampling_rate as number;\n\n return {\n audio,\n sampleRate,\n duration: audio.length / sampleRate,\n voice,\n totalTime,\n };\n }\n\n /**\n * Stream speech generation\n */\n async *speakStream(\n text: string,\n options: SpeakOptions = {},\n ): AsyncGenerator<AudioChunk, SpeakResult, unknown> {\n await this.ensureLoaded({ onProgress: options.onProgress });\n\n const { voice = this.modelConfig.defaultVoice, speed = 1.0 } = options;\n\n const voiceInfo = this.getVoice(voice);\n if (!voiceInfo) {\n throw new Error(`Unknown voice: ${voice}. Use listVoices() to see available options.`);\n }\n\n const startTime = performance.now();\n\n // Split text into sentences for streaming\n const sentences = text.split(SENTENCE_SPLIT_REGEX).filter((s) => s.trim());\n const allAudio: Float32Array[] = [];\n let chunkIndex = 0;\n let sampleRate = this.modelConfig.sampleRate;\n\n for (let i = 0; i < sentences.length; i++) {\n const sentence = sentences[i];\n if (!sentence.trim()) continue;\n\n const result = await this.speak(sentence, { voice, speed });\n sampleRate = result.sampleRate;\n allAudio.push(result.audio);\n\n const chunk: AudioChunk = {\n samples: result.audio,\n sampleRate: result.sampleRate,\n index: chunkIndex++,\n isFinal: i === sentences.length - 1,\n };\n\n yield chunk;\n options.onAudioChunk?.(chunk);\n }\n\n // Concatenate all audio\n const totalLength = allAudio.reduce((sum, arr) => sum + arr.length, 0);\n const fullAudio = new Float32Array(totalLength);\n let offset = 0;\n for (const chunk of allAudio) {\n fullAudio.set(chunk, offset);\n offset += chunk.length;\n }\n\n const totalTime = performance.now() - startTime;\n\n return {\n audio: fullAudio,\n sampleRate,\n duration: fullAudio.length / sampleRate,\n voice,\n totalTime,\n };\n }\n\n isLoaded(): boolean {\n return this._isLoaded;\n }\n\n getDeviceMode(): \"webgpu\" | \"cpu\" {\n return this._deviceMode;\n }\n\n getModelInfo(): TTSModelConfig {\n return { ...this.modelConfig };\n }\n\n getSampleRate(): number {\n return this.modelConfig.sampleRate;\n }\n\n async dispose(): Promise<void> {\n this.pipeline = null;\n this.voiceEmbeddings.clear();\n this._isLoaded = false;\n this.loadPromise = null;\n }\n}\n\n// ============================================\n// Unified TTS Factory\n// ============================================\n\nexport type TTSBackend = KokoroTTS | SupertonicTTS;\n\n/**\n * Create a TTS instance based on model ID\n */\nexport function createTTS(modelId: string = \"kokoro-82m\"): TTSBackend {\n if (modelId.startsWith(\"supertonic\")) {\n return new SupertonicTTS(modelId);\n }\n return new KokoroTTS(modelId);\n}\n\nexport default KokoroTTS;\n"],"mappings":";AAoCA,MAAM,uBAAuB;;;;;;;;AAa7B,MAAaA,gBAA6B;CAExC;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CAED;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CAED;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CAED;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACF;;;;;AAUD,MAAaC,oBAAiC;CAC5C;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACD;EACE,IAAI;EACJ,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa;EACb,eAAe;EAChB;CACF;AAMD,MAAaC,aAA6C;CACxD,cAAc;EACZ,IAAI;EACJ,MAAM;EACN,aAAa;EACb,MAAM;EACN,YAAY;EACZ,QAAQ;EACR,cAAc;EACd,WAAW,CAAC,SAAS,QAAQ;EAC9B;CACD,kBAAkB;EAChB,IAAI;EACJ,MAAM;EACN,aAAa;EACb,MAAM;EACN,YAAY;EACZ,QAAQ;EACR,cAAc;EACd,WAAW,CAAC,KAAK;EAClB;CACF;;;;AAKD,SAAgB,kBAAkB,SAAwC;AACxE,QAAO,WAAW,YAAY;;;;;AAMhC,SAAgB,gBAAkC;AAChD,QAAO,OAAO,OAAO,WAAW;;;;;;;;AA+BlC,IAAa,YAAb,MAAuB;CACrB,AAAQ,iBAA0C;CAClD,AAAQ;CACR,AAAQ,cAAoC;CAC5C,AAAQ,YAAY;CACpB,AAAQ,cAAgC;CAExC,YAAY,UAAU,cAAc;EAClC,MAAM,SAAS,kBAAkB,QAAQ;AACzC,MAAI,CAAC,OACH,OAAM,IAAI,MACR,sBAAsB,QAAQ,eAAe,OAAO,KAAK,WAAW,CAAC,KAAK,KAAK,GAChF;AAEH,OAAK,cAAc;;;;;;;;;;;;;;CAmBrB,MAAM,KAAK,UAA0B,EAAE,EAAiB;AACtD,MAAI,KAAK,UACP;AAIF,MAAI,KAAK,YACP,QAAO,KAAK;AAGd,OAAK,cAAc,KAAK,MAAM,QAAQ;AACtC,QAAM,KAAK;;CAGb,MAAc,MAAM,UAA0B,EAAE,EAAiB;EAC/D,MAAM,EAAE,YAAY,SAAS,WAAW;AAExC,eAAa,EAAE,QAAQ,sBAAsB,KAAK,YAAY,GAAG,OAAO,CAAC;AAEzE,MAAI;GAIF,MAAM,EAAE,WAAW,aADE,MAAM,OAAO;GAIlC,MAAM,YAAY,OAAO,WAAW;GACpC,IAAIC,QAAiD;AAErD,OAAI,WAAW,YAAa,WAAW,UAAU,aAAa,SAAS,WAAY;AACjF,YAAQ;AACR,SAAK,cAAc;UACd;AACL,YAAQ;AACR,SAAK,cAAc;;AAGrB,gBAAa,EAAE,QAAQ,sBAAsB,MAAM,gBAAgB,CAAC;AAOpE,QAAK,iBAAkB,MAAM,SAAS,gBAAgB,KAAK,YAAY,MAAM;IAC3E;IACA,oBAAoB,aAAkB;AACpC,SAAI,SAAS,WAAW,cAAc,SAAS,KAC7C,cAAa;MACX,QAAQ,eAAe,SAAS;MAChC,UAAU,KAAK,MAAM,SAAS,YAAY,EAAE;MAC5C,MAAM,SAAS;MAChB,CAAC;cACO,SAAS,WAAW,QAC7B,cAAa,EAAE,QAAQ,eAAe,CAAC;;IAG5C,CAAC;AAEF,QAAK,YAAY;AACjB,gBAAa,EAAE,QAAQ,UAAU,KAAK,YAAY,aAAa,CAAC,KAAK,CAAC;WAC/D,OAAO;AACd,QAAK,cAAc;AACnB,SAAM;;;;;;CAOV,MAAM,aAAa,SAAyC;AAC1D,MAAI,CAAC,KAAK,UACR,OAAM,KAAK,KAAK,QAAQ;;;;;;;;;;;CAiB5B,aAA0B;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,OAAO;;;;;CAMrC,SAAS,SAAmC;AAC1C,SAAO,KAAK,YAAY,OAAO,MAAM,MAAM,EAAE,OAAO,QAAQ,IAAI;;;;;CAMlE,kBAAkB,QAAwC;AACxD,SAAO,KAAK,YAAY,OAAO,QAAQ,MAAM,EAAE,WAAW,OAAO;;;;;CAMnE,oBAAoB,UAA+B;AACjD,SAAO,KAAK,YAAY,OAAO,QAC5B,MAAM,EAAE,aAAa,YAAY,EAAE,SAAS,WAAW,SAAS,CAClE;;;;;;;;;;;;;;;;;;;;;;CA2BH,MAAM,MAAM,MAAc,UAAwB,EAAE,EAAwB;AAC1E,QAAM,KAAK,aAAa,EAAE,YAAY,QAAQ,YAAY,CAAC;EAE3D,MAAM,EAAE,QAAQ,KAAK,YAAY,cAAc,QAAQ,MAAQ;AAI/D,MAAI,CADc,KAAK,SAAS,MAAM,CAEpC,OAAM,IAAI,MAAM,kBAAkB,MAAM,8CAA8C;AAGxF,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,YAAY,YAAY,KAAK;EAGnC,MAAM,SAAS,MAAM,KAAK,eAAe,SAAS,MAAM;GACtD;GACA;GACD,CAAC;EAEF,MAAM,YAAY,YAAY,KAAK,GAAG;AAEtC,SAAO;GACL,OAAO,OAAO;GACd,YAAY,OAAO;GACnB,UAAU,OAAO,MAAM,SAAS,OAAO;GACvC;GACA;GACD;;;;;;;;;;;;;;;CAgBH,OAAO,YACL,MACA,UAAwB,EAAE,EACwB;AAClD,QAAM,KAAK,aAAa,EAAE,YAAY,QAAQ,YAAY,CAAC;EAE3D,MAAM,EAAE,QAAQ,KAAK,YAAY,cAAc,QAAQ,MAAQ;AAI/D,MAAI,CADc,KAAK,SAAS,MAAM,CAEpC,OAAM,IAAI,MAAM,kBAAkB,MAAM,8CAA8C;AAGxF,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,YAAY,YAAY,KAAK;EAGnC,MAAM,YAAY,KAAK,mBAAmB,KAAK;EAC/C,MAAMC,WAA2B,EAAE;EACnC,IAAI,aAAa;EACjB,IAAI,aAAa,KAAK,YAAY;AAElC,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;GACzC,MAAM,WAAW,UAAU;AAC3B,OAAI,CAAC,SAAS,MAAM,CAClB;GAGF,MAAM,SAAS,MAAM,KAAK,eAAe,SAAS,UAAU;IAC1D;IACA;IACD,CAAC;AAEF,gBAAa,OAAO;AACpB,YAAS,KAAK,OAAO,MAAM;GAE3B,MAAMC,QAAoB;IACxB,SAAS,OAAO;IAChB,YAAY,OAAO;IACnB,OAAO;IACP,SAAS,MAAM,UAAU,SAAS;IACnC;AAED,SAAM;AACN,WAAQ,eAAe,MAAM;;EAI/B,MAAM,cAAc,SAAS,QAAQ,KAAK,QAAQ,MAAM,IAAI,QAAQ,EAAE;EACtE,MAAM,YAAY,IAAI,aAAa,YAAY;EAC/C,IAAI,SAAS;AACb,OAAK,MAAM,SAAS,UAAU;AAC5B,aAAU,IAAI,OAAO,OAAO;AAC5B,aAAU,MAAM;;EAGlB,MAAM,YAAY,YAAY,KAAK,GAAG;AAEtC,SAAO;GACL,OAAO;GACP;GACA,UAAU,UAAU,SAAS;GAC7B;GACA;GACD;;;;;CAMH,AAAQ,mBAAmB,MAAwB;AAEjD,SAAO,KAAK,MAAM,qBAAqB,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC;;;;;CAUjE,WAAoB;AAClB,SAAO,KAAK;;;;;CAMd,gBAAkC;AAChC,SAAO,KAAK;;;;;CAMd,eAA+B;AAC7B,SAAO,EAAE,GAAG,KAAK,aAAa;;;;;CAMhC,gBAAwB;AACtB,SAAO,KAAK,YAAY;;;;;CAU1B,MAAM,UAAyB;AAG7B,OAAK,iBAAiB;AACtB,OAAK,YAAY;AACjB,OAAK,cAAc;;;;;;;;;;AAevB,IAAa,gBAAb,MAA2B;CACzB,AAAQ,WAAgB;CACxB,AAAQ;CACR,AAAQ,cAAoC;CAC5C,AAAQ,YAAY;CACpB,AAAQ,cAAgC;CACxC,AAAQ,kCAA6C,IAAI,KAAK;CAE9D,YAAY,UAAU,kBAAkB;EACtC,MAAM,SAAS,kBAAkB,QAAQ;AACzC,MAAI,CAAC,OACH,OAAM,IAAI,MACR,sBAAsB,QAAQ,eAAe,OAAO,KAAK,WAAW,CAAC,KAAK,KAAK,GAChF;AAEH,OAAK,cAAc;;;;;CAMrB,MAAM,KAAK,UAA0B,EAAE,EAAiB;AACtD,MAAI,KAAK,UACP;AAGF,MAAI,KAAK,YACP,QAAO,KAAK;AAGd,OAAK,cAAc,KAAK,MAAM,QAAQ;AACtC,QAAM,KAAK;;CAGb,MAAc,MAAM,UAA0B,EAAE,EAAiB;EAC/D,MAAM,EAAE,YAAY,SAAS,WAAW;AAExC,eAAa,EAAE,QAAQ,sBAAsB,KAAK,YAAY,GAAG,OAAO,CAAC;AAEzE,MAAI;GAEF,MAAM,YAAY,OAAO,WAAW;GAIpC,MAAM,EAAE,UAAU,QAAQ,MAAM,OAAO;AAGvC,OAAI,aAAa,IAAI,UAAU,MAAM,KACnC,KAAI,SAAS,KAAK,KAAK,YACrB;AAGJ,OAAI,WAAW,YAAa,WAAW,UAAU,aAAa,SAAS,UACrE,MAAK,cAAc;OAEnB,MAAK,cAAc;AAGrB,gBAAa,EAAE,QAAQ,+BAA+B,CAAC;AAGvD,QAAK,WAAW,MAAM,SAAS,kBAAkB,KAAK,YAAY,MAAM;IACtE,OAAO;IACP,QAAQ,KAAK;IACb,oBAAoB,aAAkB;AACpC,SAAI,SAAS,WAAW,cAAc,SAAS,KAC7C,cAAa;MACX,QAAQ,eAAe,SAAS;MAChC,UAAU,KAAK,MAAM,SAAS,YAAY,EAAE;MAC5C,MAAM,SAAS;MAChB,CAAC;;IAGP,CAAC;AAGF,gBAAa,EAAE,QAAQ,+BAA+B,CAAC;AACvD,SAAM,KAAK,qBAAqB;AAEhC,QAAK,YAAY;AACjB,gBAAa,EAAE,QAAQ,UAAU,KAAK,YAAY,aAAa,CAAC,KAAK,CAAC;WAC/D,OAAO;AACd,QAAK,cAAc;AACnB,SAAM;;;;;;;CAQV,MAAc,sBAAqC;CAOnD,MAAM,aAAa,SAAyC;AAC1D,MAAI,CAAC,KAAK,UACR,OAAM,KAAK,KAAK,QAAQ;;CAI5B,aAA0B;AACxB,SAAO,CAAC,GAAG,KAAK,YAAY,OAAO;;CAGrC,SAAS,SAAmC;AAC1C,SAAO,KAAK,YAAY,OAAO,MAAM,MAAM,EAAE,OAAO,QAAQ,IAAI;;CAGlE,kBAAkB,QAAwC;AACxD,SAAO,KAAK,YAAY,OAAO,QAAQ,MAAM,EAAE,WAAW,OAAO;;;;;CAMnE,MAAM,MAAM,MAAc,UAAwB,EAAE,EAAwB;AAC1E,QAAM,KAAK,aAAa,EAAE,YAAY,QAAQ,YAAY,CAAC;EAE3D,MAAM,EAAE,QAAQ,KAAK,YAAY,iBAAiB;AAIlD,MAAI,CADc,KAAK,SAAS,MAAM,CAEpC,OAAM,IAAI,MAAM,kBAAkB,MAAM,8CAA8C;AAGxF,MAAI,CAAC,KAAK,SACR,OAAM,IAAI,MAAM,mBAAmB;EAGrC,MAAM,YAAY,YAAY,KAAK;EAInC,IAAI,mBAAmB,KAAK,gBAAgB,IAAI,MAAM;AACtD,MAAI,CAAC,iBAEH,KAAI;GACF,MAAM,WAAW,0BAA0B,KAAK,YAAY,KAAK,uBAAuB,MAAM;GAC9F,MAAM,WAAW,MAAM,MAAM,SAAS;AACtC,OAAI,SAAS,IAAI;IACf,MAAM,SAAS,MAAM,SAAS,aAAa;AAC3C,uBAAmB,IAAI,aAAa,OAAO;AAC3C,SAAK,gBAAgB,IAAI,OAAO,iBAAiB;SAEjD,OAAM,IAAI,MAAM,yBAAyB,SAAS,SAAS;UAEvD;AAEN,sBAAmB,IAAI,aAAa,MAAU,CAAC,KAAK,GAAI;AACxD,QAAK,gBAAgB,IAAI,OAAO,iBAAiB;;EAKrD,MAAM,SAAS,MAAM,KAAK,SAAS,MAAM,EACvC,oBAAoB,kBACrB,CAAC;EAEF,MAAM,YAAY,YAAY,KAAK,GAAG;EACtC,MAAM,QAAQ,OAAO;EACrB,MAAM,aAAa,OAAO;AAE1B,SAAO;GACL;GACA;GACA,UAAU,MAAM,SAAS;GACzB;GACA;GACD;;;;;CAMH,OAAO,YACL,MACA,UAAwB,EAAE,EACwB;AAClD,QAAM,KAAK,aAAa,EAAE,YAAY,QAAQ,YAAY,CAAC;EAE3D,MAAM,EAAE,QAAQ,KAAK,YAAY,cAAc,QAAQ,MAAQ;AAG/D,MAAI,CADc,KAAK,SAAS,MAAM,CAEpC,OAAM,IAAI,MAAM,kBAAkB,MAAM,8CAA8C;EAGxF,MAAM,YAAY,YAAY,KAAK;EAGnC,MAAM,YAAY,KAAK,MAAM,qBAAqB,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC;EAC1E,MAAMD,WAA2B,EAAE;EACnC,IAAI,aAAa;EACjB,IAAI,aAAa,KAAK,YAAY;AAElC,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;GACzC,MAAM,WAAW,UAAU;AAC3B,OAAI,CAAC,SAAS,MAAM,CAAE;GAEtB,MAAM,SAAS,MAAM,KAAK,MAAM,UAAU;IAAE;IAAO;IAAO,CAAC;AAC3D,gBAAa,OAAO;AACpB,YAAS,KAAK,OAAO,MAAM;GAE3B,MAAMC,QAAoB;IACxB,SAAS,OAAO;IAChB,YAAY,OAAO;IACnB,OAAO;IACP,SAAS,MAAM,UAAU,SAAS;IACnC;AAED,SAAM;AACN,WAAQ,eAAe,MAAM;;EAI/B,MAAM,cAAc,SAAS,QAAQ,KAAK,QAAQ,MAAM,IAAI,QAAQ,EAAE;EACtE,MAAM,YAAY,IAAI,aAAa,YAAY;EAC/C,IAAI,SAAS;AACb,OAAK,MAAM,SAAS,UAAU;AAC5B,aAAU,IAAI,OAAO,OAAO;AAC5B,aAAU,MAAM;;EAGlB,MAAM,YAAY,YAAY,KAAK,GAAG;AAEtC,SAAO;GACL,OAAO;GACP;GACA,UAAU,UAAU,SAAS;GAC7B;GACA;GACD;;CAGH,WAAoB;AAClB,SAAO,KAAK;;CAGd,gBAAkC;AAChC,SAAO,KAAK;;CAGd,eAA+B;AAC7B,SAAO,EAAE,GAAG,KAAK,aAAa;;CAGhC,gBAAwB;AACtB,SAAO,KAAK,YAAY;;CAG1B,MAAM,UAAyB;AAC7B,OAAK,WAAW;AAChB,OAAK,gBAAgB,OAAO;AAC5B,OAAK,YAAY;AACjB,OAAK,cAAc;;;;;;AAavB,SAAgB,UAAU,UAAkB,cAA0B;AACpE,KAAI,QAAQ,WAAW,aAAa,CAClC,QAAO,IAAI,cAAc,QAAQ;AAEnC,QAAO,IAAI,UAAU,QAAQ"}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/core/types.d.ts
|
|
4
|
+
|
|
5
|
+
type ModelConfig = {
|
|
6
|
+
id: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
description: string;
|
|
9
|
+
size: string;
|
|
10
|
+
contextLength: number;
|
|
11
|
+
supportsThinking: boolean;
|
|
12
|
+
supportsJson: boolean;
|
|
13
|
+
/** Whether model supports vision/image input */
|
|
14
|
+
supportsVision?: boolean;
|
|
15
|
+
/** Vision encoder size (for display, e.g., "0.4B") */
|
|
16
|
+
visionEncoderSize?: string;
|
|
17
|
+
family: "qwen" | "smollm" | "phi" | "mistral" | "llama" | "other";
|
|
18
|
+
};
|
|
19
|
+
type ModelSource = {
|
|
20
|
+
type: "builtin" | "huggingface" | "local";
|
|
21
|
+
path: string;
|
|
22
|
+
};
|
|
23
|
+
type ImageInput = {
|
|
24
|
+
/** Image source: URL, base64 data URI, or local file path */
|
|
25
|
+
source: string;
|
|
26
|
+
/** Optional alt text for context */
|
|
27
|
+
alt?: string;
|
|
28
|
+
};
|
|
29
|
+
type GenerateOptions = {
|
|
30
|
+
/** Maximum tokens to generate (default: 256) */
|
|
31
|
+
maxTokens?: number;
|
|
32
|
+
/** Temperature for sampling, 0-2 (default: 0.7) */
|
|
33
|
+
temperature?: number;
|
|
34
|
+
/** Top-p sampling (default: 0.9) */
|
|
35
|
+
topP?: number;
|
|
36
|
+
/** Top-k sampling (default: 50) */
|
|
37
|
+
topK?: number;
|
|
38
|
+
/** Stop sequences */
|
|
39
|
+
stopSequences?: string[];
|
|
40
|
+
/** System prompt */
|
|
41
|
+
system?: string;
|
|
42
|
+
/** Enable thinking/reasoning mode (Qwen3) */
|
|
43
|
+
thinking?: boolean;
|
|
44
|
+
/** Callback for each token (streaming) */
|
|
45
|
+
onToken?: (token: string) => void;
|
|
46
|
+
/** Images to include (only used if model supports vision) */
|
|
47
|
+
images?: ImageInput[];
|
|
48
|
+
/** Enable response caching (default: false) */
|
|
49
|
+
cache?: boolean;
|
|
50
|
+
/** Cache TTL in milliseconds (default: 5 minutes) */
|
|
51
|
+
cacheTtl?: number;
|
|
52
|
+
};
|
|
53
|
+
type GenerateResult = {
|
|
54
|
+
/** Generated text */
|
|
55
|
+
text: string;
|
|
56
|
+
/** Thinking/reasoning (if enabled) */
|
|
57
|
+
thinking?: string;
|
|
58
|
+
/** Tokens generated */
|
|
59
|
+
tokensGenerated: number;
|
|
60
|
+
/** Generation speed */
|
|
61
|
+
tokensPerSecond: number;
|
|
62
|
+
/** Total time in ms */
|
|
63
|
+
totalTime: number;
|
|
64
|
+
/** Why generation stopped */
|
|
65
|
+
finishReason: "stop" | "length" | "error";
|
|
66
|
+
/** Which provider was used (for hybrid mode) */
|
|
67
|
+
provider?: "local" | "openai" | "anthropic";
|
|
68
|
+
/** Whether result came from cache */
|
|
69
|
+
cached?: boolean;
|
|
70
|
+
};
|
|
71
|
+
type JsonOptions<T = unknown> = {
|
|
72
|
+
/** Zod schema for validation */
|
|
73
|
+
schema: z.ZodType<T>;
|
|
74
|
+
/** Number of retries on invalid JSON (default: 3) */
|
|
75
|
+
retries?: number;
|
|
76
|
+
/** Temperature (lower = more deterministic, default: 0.3) */
|
|
77
|
+
temperature?: number;
|
|
78
|
+
/** System prompt override */
|
|
79
|
+
system?: string;
|
|
80
|
+
};
|
|
81
|
+
type EmbedOptions = {
|
|
82
|
+
/** Model to use for embeddings */
|
|
83
|
+
model?: string;
|
|
84
|
+
/** Normalize vectors (default: true) */
|
|
85
|
+
normalize?: boolean;
|
|
86
|
+
};
|
|
87
|
+
type EmbedResult = {
|
|
88
|
+
/** Embedding vector */
|
|
89
|
+
vector: number[];
|
|
90
|
+
/** Original text */
|
|
91
|
+
text: string;
|
|
92
|
+
/** Time in ms */
|
|
93
|
+
totalTime: number;
|
|
94
|
+
};
|
|
95
|
+
type LoadOptions = {
|
|
96
|
+
/** Progress callback */
|
|
97
|
+
onProgress?: (info: ProgressInfo) => void;
|
|
98
|
+
/** Device: 'auto', 'gpu', 'cpu', 'webgpu' (default: 'auto') */
|
|
99
|
+
device?: "auto" | "gpu" | "cpu" | "webgpu";
|
|
100
|
+
/** Quantization: 'q4', 'q8', 'fp16', 'fp32' (default: 'q4') */
|
|
101
|
+
dtype?: "q4" | "q8" | "fp16" | "fp32";
|
|
102
|
+
/** Override context length */
|
|
103
|
+
contextLength?: number;
|
|
104
|
+
};
|
|
105
|
+
type ProgressInfo = {
|
|
106
|
+
status: string;
|
|
107
|
+
progress?: number;
|
|
108
|
+
file?: string;
|
|
109
|
+
loaded?: number;
|
|
110
|
+
total?: number;
|
|
111
|
+
};
|
|
112
|
+
type GerbilConfig = {
|
|
113
|
+
/** Default model */
|
|
114
|
+
model?: string;
|
|
115
|
+
/** Default device */
|
|
116
|
+
device?: "auto" | "gpu" | "cpu";
|
|
117
|
+
/** Default quantization */
|
|
118
|
+
dtype?: "q4" | "q8" | "fp16" | "fp32";
|
|
119
|
+
/** Cache configuration */
|
|
120
|
+
cache?: CacheConfig;
|
|
121
|
+
/** Fallback configuration */
|
|
122
|
+
fallback?: FallbackConfig;
|
|
123
|
+
};
|
|
124
|
+
type CacheConfig = {
|
|
125
|
+
/** Enable caching (default: true) */
|
|
126
|
+
enabled?: boolean;
|
|
127
|
+
/** Time-to-live in seconds (default: 3600) */
|
|
128
|
+
ttl?: number;
|
|
129
|
+
/** Max cache size (default: "500mb") */
|
|
130
|
+
maxSize?: string;
|
|
131
|
+
/** Storage backend */
|
|
132
|
+
storage?: "memory" | "disk" | "redis";
|
|
133
|
+
/** Redis URL (if storage is redis) */
|
|
134
|
+
redisUrl?: string;
|
|
135
|
+
};
|
|
136
|
+
type FallbackConfig = {
|
|
137
|
+
/** Fallback provider */
|
|
138
|
+
provider: "openai" | "anthropic";
|
|
139
|
+
/** API key */
|
|
140
|
+
apiKey: string;
|
|
141
|
+
/** Model to use */
|
|
142
|
+
model: string;
|
|
143
|
+
/** When to fallback */
|
|
144
|
+
when: "timeout" | "error" | "always-verify";
|
|
145
|
+
/** Timeout in ms before fallback (default: 5000) */
|
|
146
|
+
timeout?: number;
|
|
147
|
+
};
|
|
148
|
+
type SessionStats = {
|
|
149
|
+
prompts: number;
|
|
150
|
+
tokensIn: number;
|
|
151
|
+
tokensOut: number;
|
|
152
|
+
avgSpeed: number;
|
|
153
|
+
totalTime: number;
|
|
154
|
+
cacheHits: number;
|
|
155
|
+
cacheMisses: number;
|
|
156
|
+
};
|
|
157
|
+
type ModelStats = {
|
|
158
|
+
modelId: string;
|
|
159
|
+
avgSpeed: number;
|
|
160
|
+
totalGenerations: number;
|
|
161
|
+
totalTokens: number;
|
|
162
|
+
};
|
|
163
|
+
type SystemInfo = {
|
|
164
|
+
version: string;
|
|
165
|
+
model: ModelConfig | null;
|
|
166
|
+
device: {
|
|
167
|
+
backend: string;
|
|
168
|
+
gpu: string | null;
|
|
169
|
+
vram: string | null;
|
|
170
|
+
status: "ready" | "loading" | "error";
|
|
171
|
+
};
|
|
172
|
+
context: {
|
|
173
|
+
max: number;
|
|
174
|
+
used: number;
|
|
175
|
+
available: number;
|
|
176
|
+
};
|
|
177
|
+
cache: {
|
|
178
|
+
location: string;
|
|
179
|
+
size: string;
|
|
180
|
+
modelCount: number;
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
type GerbilModelSettings = {
|
|
184
|
+
/** Enable thinking mode */
|
|
185
|
+
thinking?: boolean;
|
|
186
|
+
/** Device to use */
|
|
187
|
+
device?: "auto" | "gpu" | "cpu";
|
|
188
|
+
/** Quantization level */
|
|
189
|
+
dtype?: "q4" | "q8" | "fp16" | "fp32";
|
|
190
|
+
};
|
|
191
|
+
type GerbilProviderSettings = {
|
|
192
|
+
/** Default device */
|
|
193
|
+
device?: "auto" | "gpu" | "cpu";
|
|
194
|
+
/** Default quantization */
|
|
195
|
+
dtype?: "q4" | "q8" | "fp16" | "fp32";
|
|
196
|
+
};
|
|
197
|
+
type VoiceInfo = {
|
|
198
|
+
/** Voice ID (e.g., "af_bella", "am_adam") */
|
|
199
|
+
id: string;
|
|
200
|
+
/** Display name (e.g., "Bella", "Adam") */
|
|
201
|
+
name: string;
|
|
202
|
+
/** Gender: male, female, or neutral */
|
|
203
|
+
gender: "male" | "female" | "neutral";
|
|
204
|
+
/** Language code (e.g., "en", "en-us", "zh") */
|
|
205
|
+
language: string;
|
|
206
|
+
/** Optional description */
|
|
207
|
+
description?: string;
|
|
208
|
+
/** Speaker embedding file name (internal) */
|
|
209
|
+
embeddingFile?: string;
|
|
210
|
+
};
|
|
211
|
+
type TTSModelConfig = {
|
|
212
|
+
/** Model ID (e.g., "kokoro-82m") */
|
|
213
|
+
id: string;
|
|
214
|
+
/** HuggingFace repo path */
|
|
215
|
+
repo: string;
|
|
216
|
+
/** Human-readable description */
|
|
217
|
+
description: string;
|
|
218
|
+
/** Approximate model size */
|
|
219
|
+
size: string;
|
|
220
|
+
/** Output sample rate in Hz (e.g., 24000) */
|
|
221
|
+
sampleRate: number;
|
|
222
|
+
/** Available voices */
|
|
223
|
+
voices: VoiceInfo[];
|
|
224
|
+
/** Default voice ID */
|
|
225
|
+
defaultVoice: string;
|
|
226
|
+
/** Supported languages */
|
|
227
|
+
languages: string[];
|
|
228
|
+
};
|
|
229
|
+
type SpeakOptions = {
|
|
230
|
+
/** Voice ID to use (default: model's default voice) */
|
|
231
|
+
voice?: string;
|
|
232
|
+
/** Speech speed multiplier (0.5 = half speed, 2.0 = double speed, default: 1.0) */
|
|
233
|
+
speed?: number;
|
|
234
|
+
/** Progress callback */
|
|
235
|
+
onProgress?: (info: ProgressInfo) => void;
|
|
236
|
+
/** Callback for audio chunks during streaming */
|
|
237
|
+
onAudioChunk?: (chunk: AudioChunk) => void;
|
|
238
|
+
};
|
|
239
|
+
type AudioChunk = {
|
|
240
|
+
/** Raw PCM audio samples (Float32Array) */
|
|
241
|
+
samples: Float32Array;
|
|
242
|
+
/** Sample rate in Hz */
|
|
243
|
+
sampleRate: number;
|
|
244
|
+
/** Chunk index (0-based) */
|
|
245
|
+
index: number;
|
|
246
|
+
/** Whether this is the final chunk */
|
|
247
|
+
isFinal: boolean;
|
|
248
|
+
};
|
|
249
|
+
type SpeakResult = {
|
|
250
|
+
/** Raw PCM audio samples (Float32Array) */
|
|
251
|
+
audio: Float32Array;
|
|
252
|
+
/** Sample rate in Hz */
|
|
253
|
+
sampleRate: number;
|
|
254
|
+
/** Audio duration in seconds */
|
|
255
|
+
duration: number;
|
|
256
|
+
/** Voice used */
|
|
257
|
+
voice: string;
|
|
258
|
+
/** Total processing time in ms */
|
|
259
|
+
totalTime: number;
|
|
260
|
+
};
|
|
261
|
+
type LoadTTSOptions = {
|
|
262
|
+
/** Progress callback */
|
|
263
|
+
onProgress?: (info: ProgressInfo) => void;
|
|
264
|
+
/** Device: 'auto', 'webgpu', 'cpu' (default: 'auto') */
|
|
265
|
+
device?: "auto" | "webgpu" | "cpu";
|
|
266
|
+
};
|
|
267
|
+
type STTModelConfig = {
|
|
268
|
+
/** Model ID (e.g., "whisper-tiny.en") */
|
|
269
|
+
id: string;
|
|
270
|
+
/** HuggingFace repo path */
|
|
271
|
+
repo: string;
|
|
272
|
+
/** Human-readable description */
|
|
273
|
+
description: string;
|
|
274
|
+
/** Model size (e.g., "39M", "244M") */
|
|
275
|
+
size: string;
|
|
276
|
+
/** Whether model supports multiple languages */
|
|
277
|
+
multilingual: boolean;
|
|
278
|
+
/** Supported languages (ISO 639-1 codes) */
|
|
279
|
+
languages: string[];
|
|
280
|
+
/** Expected sample rate (default: 16000) */
|
|
281
|
+
sampleRate: number;
|
|
282
|
+
};
|
|
283
|
+
type TranscribeOptions = {
|
|
284
|
+
/** Language hint (ISO 639-1 code like "en", "es", "fr") - only for multilingual models */
|
|
285
|
+
language?: string;
|
|
286
|
+
/** Return word/segment timestamps */
|
|
287
|
+
timestamps?: boolean;
|
|
288
|
+
/** Progress callback */
|
|
289
|
+
onProgress?: (info: ProgressInfo) => void;
|
|
290
|
+
};
|
|
291
|
+
type TranscribeSegment = {
|
|
292
|
+
/** Segment text */
|
|
293
|
+
text: string;
|
|
294
|
+
/** Start time in seconds */
|
|
295
|
+
start: number;
|
|
296
|
+
/** End time in seconds */
|
|
297
|
+
end: number;
|
|
298
|
+
};
|
|
299
|
+
type TranscribeResult = {
|
|
300
|
+
/** Full transcribed text */
|
|
301
|
+
text: string;
|
|
302
|
+
/** Detected or specified language */
|
|
303
|
+
language: string;
|
|
304
|
+
/** Segments with timestamps (if timestamps option enabled) */
|
|
305
|
+
segments?: TranscribeSegment[];
|
|
306
|
+
/** Audio duration in seconds */
|
|
307
|
+
duration: number;
|
|
308
|
+
/** Total processing time in ms */
|
|
309
|
+
totalTime: number;
|
|
310
|
+
};
|
|
311
|
+
type LoadSTTOptions = {
|
|
312
|
+
/** Progress callback */
|
|
313
|
+
onProgress?: (info: ProgressInfo) => void;
|
|
314
|
+
/** Device: 'auto', 'webgpu', 'cpu' (default: 'auto') */
|
|
315
|
+
device?: "auto" | "webgpu" | "cpu";
|
|
316
|
+
};
|
|
317
|
+
type StreamingTranscriptionOptions = {
|
|
318
|
+
/** Interval between transcriptions in ms (default: 3000) */
|
|
319
|
+
chunkDuration?: number;
|
|
320
|
+
/** Minimum audio samples before transcribing (default: 8000 = 0.5s at 16kHz) */
|
|
321
|
+
minChunkSize?: number;
|
|
322
|
+
/** Callback for each transcribed chunk */
|
|
323
|
+
onChunk?: (text: string, chunkIndex: number) => void;
|
|
324
|
+
/** Callback with full accumulated transcript */
|
|
325
|
+
onTranscript?: (fullText: string) => void;
|
|
326
|
+
/** Callback on transcription error */
|
|
327
|
+
onError?: (error: string) => void;
|
|
328
|
+
/** Language hint (for multilingual models) */
|
|
329
|
+
language?: string;
|
|
330
|
+
};
|
|
331
|
+
type StreamingTranscriptionSession = {
|
|
332
|
+
/** Feed audio data to the buffer (Float32Array at 16kHz) */
|
|
333
|
+
feedAudio: (audio: Float32Array) => void;
|
|
334
|
+
/** Manually trigger transcription of buffered audio */
|
|
335
|
+
flush: () => Promise<string>;
|
|
336
|
+
/** Start automatic interval-based transcription */
|
|
337
|
+
start: () => void;
|
|
338
|
+
/** Stop transcription and return final transcript */
|
|
339
|
+
stop: () => Promise<string>;
|
|
340
|
+
/** Immediately abort without final transcription (for cleanup) */
|
|
341
|
+
abort: () => void;
|
|
342
|
+
/** Check if session is running */
|
|
343
|
+
isRunning: () => boolean;
|
|
344
|
+
/** Get current full transcript */
|
|
345
|
+
getTranscript: () => string;
|
|
346
|
+
/** Get number of chunks transcribed */
|
|
347
|
+
getChunkCount: () => number;
|
|
348
|
+
/** Reset session (clear buffer and transcript) */
|
|
349
|
+
reset: () => void;
|
|
350
|
+
};
|
|
351
|
+
//#endregion
|
|
352
|
+
export { TranscribeSegment as A, SpeakResult as C, TTSModelConfig as D, SystemInfo as E, TranscribeOptions as O, SpeakOptions as S, StreamingTranscriptionSession as T, ModelSource as _, FallbackConfig as a, STTModelConfig as b, GerbilConfig as c, ImageInput as d, JsonOptions as f, ModelConfig as g, LoadTTSOptions as h, EmbedResult as i, VoiceInfo as j, TranscribeResult as k, GerbilModelSettings as l, LoadSTTOptions as m, CacheConfig as n, GenerateOptions as o, LoadOptions as p, EmbedOptions as r, GenerateResult as s, AudioChunk as t, GerbilProviderSettings as u, ModelStats as v, StreamingTranscriptionOptions as w, SessionStats as x, ProgressInfo as y };
|
|
353
|
+
//# sourceMappingURL=types-CiTc7ez3.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CiTc7ez3.d.mts","names":[],"sources":["../src/core/types.ts"],"sourcesContent":[],"mappings":";;;;AAyBY,KAfA,WAAA,GAeW;EASX,EAAA,EAAA,MAAA;EAWA,IAAA,EAAA,MAAA;EAmCA,WAAA,EAAA,MAAc;EA8Bd,IAAA,EAAA,MAAA;EAkBA,aAAA,EAAY,MAAA;EAQZ,gBAAW,EAAA,OAAA;EAeX,YAAA,EAAW,OAAA;EAcX;EAYA,cAAA,CAAY,EAAA,OAAA;EAiBZ;EAiBA,iBAAc,CAAA,EAAA,MAAA;EAqBd,MAAA,EAAA,MAAA,GAAY,QAAA,GAAA,KAAA,GAAA,SAAA,GAAA,OAAA,GAAA,OAAA;AAUxB,CAAA;AAOY,KAhOA,WAAA,GAgOU;EAyBV,IAAA,EAAA,SAAA,GAAA,aAAmB,GAAA,OAAA;EAWnB,IAAA,EAAA,MAAA;AAYZ,CAAA;AAeY,KAtRA,UAAA,GAsRc;EAmBd;EAWA,MAAA,EAAA,MAAU;EAWV;EAaA,GAAA,CAAA,EAAA,MAAA;AAWZ,CAAA;AAiBY,KA7VA,eAAA,GA6ViB;EASjB;EASA,SAAA,CAAA,EAAA,MAAA;EAaA;EAWA,WAAA,CAAA,EAAA,MAAA;EAeA;EAES,IAAA,CAAA,EAAA,MAAA;EAEN;EAID,IAAA,CAAA,EAAA,MAAA;EAAO;;;;;;;;;WApYV;;;;;;KASC,cAAA;;;;;;;;;;;;;;;;;;KA8BA;;UAEF,CAAA,CAAE,QAAQ;;;;;;;;KAgBR,YAAA;;;;;;KAQA,WAAA;;;;;;;;KAeA,WAAA;;sBAEU;;;;;;;;KAYV,YAAA;;;;;;;KAYA,YAAA;;;;;;;;UAWF;;aAGG;;KAGD,WAAA;;;;;;;;;;;;KAiBA,cAAA;;;;;;;;;;;;KAqBA,YAAA;;;;;;;;;KAUA,UAAA;;;;;;KAOA,UAAA;;SAEH;;;;;;;;;;;;;;;;;;KAuBG,mBAAA;;;;;;;;KAWA,sBAAA;;;;;;KAYA,SAAA;;;;;;;;;;;;;;KAeA,cAAA;;;;;;;;;;;;UAYF;;;;;;KAOE,YAAA;;;;;;sBAMU;;yBAEG;;KAGb,UAAA;;WAED;;;;;;;;KASC,WAAA;;SAEH;;;;;;;;;;KAWG,cAAA;;sBAEU;;;;KASV,cAAA;;;;;;;;;;;;;;;;KAiBA,iBAAA;;;;;;sBAMU;;KAGV,iBAAA;;;;;;;;KASA,gBAAA;;;;;;aAMC;;;;;;KAOD,cAAA;;sBAEU;;;;KASV,6BAAA;;;;;;;;;;;;;;KAeA,6BAAA;;qBAES;;eAEN;;;;cAID"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils-
|
|
1
|
+
{"version":3,"file":"utils-CZBZ8dgR.mjs","names":["properties: Record<string, any>","required: string[]"],"sources":["../src/core/utils.ts"],"sourcesContent":["/**\n * Shared utility functions for Gerbil core\n */\n\nimport type { z } from \"zod\";\n\n/**\n * Convert Zod schema to JSON Schema (simplified)\n * Handles objects, arrays, primitives, enums, optionals, and defaults\n */\nexport function zodToJsonSchema(schema: z.ZodType<any>): object {\n try {\n if (\"_def\" in schema) {\n const def = (schema as any)._def;\n\n if (def.typeName === \"ZodObject\") {\n const shape = def.shape();\n const properties: Record<string, any> = {};\n const required: string[] = [];\n\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = zodToJsonSchema(value as z.ZodType<any>);\n // Check if required (not optional)\n if (!(value as any)._def?.typeName?.includes(\"Optional\")) {\n required.push(key);\n }\n }\n\n return { type: \"object\", properties, required };\n }\n if (def.typeName === \"ZodString\") {\n return { type: \"string\", description: def.description };\n }\n if (def.typeName === \"ZodNumber\") {\n return { type: \"number\", description: def.description };\n }\n if (def.typeName === \"ZodBoolean\") {\n return { type: \"boolean\" };\n }\n if (def.typeName === \"ZodArray\") {\n return { type: \"array\", items: zodToJsonSchema(def.type) };\n }\n if (def.typeName === \"ZodEnum\") {\n return { type: \"string\", enum: def.values };\n }\n if (def.typeName === \"ZodOptional\") {\n return zodToJsonSchema(def.innerType);\n }\n if (def.typeName === \"ZodDefault\") {\n const inner = zodToJsonSchema(def.innerType);\n return { ...inner, default: def.defaultValue() };\n }\n }\n } catch {}\n\n return { type: \"string\" };\n}\n\n/**\n * Extract JSON from text (finds first { } or [ ] block)\n */\nexport function extractJson(text: string): string {\n const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n return jsonMatch[0];\n }\n\n const arrayMatch = text.match(/\\[[\\s\\S]*\\]/);\n if (arrayMatch) {\n return arrayMatch[0];\n }\n\n return text;\n}\n"],"mappings":";;;;;AAUA,SAAgB,gBAAgB,QAAgC;AAC9D,KAAI;AACF,MAAI,UAAU,QAAQ;GACpB,MAAM,MAAO,OAAe;AAE5B,OAAI,IAAI,aAAa,aAAa;IAChC,MAAM,QAAQ,IAAI,OAAO;IACzB,MAAMA,aAAkC,EAAE;IAC1C,MAAMC,WAAqB,EAAE;AAE7B,SAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,EAAE;AAChD,gBAAW,OAAO,gBAAgB,MAAwB;AAE1D,SAAI,CAAE,MAAc,MAAM,UAAU,SAAS,WAAW,CACtD,UAAS,KAAK,IAAI;;AAItB,WAAO;KAAE,MAAM;KAAU;KAAY;KAAU;;AAEjD,OAAI,IAAI,aAAa,YACnB,QAAO;IAAE,MAAM;IAAU,aAAa,IAAI;IAAa;AAEzD,OAAI,IAAI,aAAa,YACnB,QAAO;IAAE,MAAM;IAAU,aAAa,IAAI;IAAa;AAEzD,OAAI,IAAI,aAAa,aACnB,QAAO,EAAE,MAAM,WAAW;AAE5B,OAAI,IAAI,aAAa,WACnB,QAAO;IAAE,MAAM;IAAS,OAAO,gBAAgB,IAAI,KAAK;IAAE;AAE5D,OAAI,IAAI,aAAa,UACnB,QAAO;IAAE,MAAM;IAAU,MAAM,IAAI;IAAQ;AAE7C,OAAI,IAAI,aAAa,cACnB,QAAO,gBAAgB,IAAI,UAAU;AAEvC,OAAI,IAAI,aAAa,aAEnB,QAAO;IAAE,GADK,gBAAgB,IAAI,UAAU;IACzB,SAAS,IAAI,cAAc;IAAE;;SAG9C;AAER,QAAO,EAAE,MAAM,UAAU;;;;;AAM3B,SAAgB,YAAY,MAAsB;CAChD,MAAM,YAAY,KAAK,MAAM,cAAc;AAC3C,KAAI,UACF,QAAO,UAAU;CAGnB,MAAM,aAAa,KAAK,MAAM,cAAc;AAC5C,KAAI,WACF,QAAO,WAAW;AAGpB,QAAO"}
|