From 3c96e8d6d176273ce059d9eeb84269beb2420333 Mon Sep 17 00:00:00 2001 From: decolua Date: Fri, 10 Apr 2026 10:17:53 +0700 Subject: [PATCH] Feat : tts --- open-sse/config/providerModels.js | 59 ++ open-sse/handlers/ttsCore.js | 419 ++++++++++ open-sse/services/model.js | 2 + public/providers/cartesia.png | Bin 0 -> 1711 bytes public/providers/cerebras.png | Bin 2295 -> 1597 bytes public/providers/cohere.png | Bin 2791 -> 4366 bytes public/providers/comfyui.png | Bin 0 -> 29834 bytes public/providers/deepseek.png | Bin 2393 -> 7727 bytes public/providers/edge-tts.png | Bin 0 -> 1348 bytes public/providers/elevenlabs.png | Bin 0 -> 933 bytes public/providers/fireworks.png | Bin 2612 -> 1729 bytes public/providers/google-tts.png | Bin 0 -> 6038 bytes public/providers/groq.png | Bin 2882 -> 4915 bytes public/providers/huggingface.png | Bin 0 -> 15383 bytes public/providers/local-device.png | Bin 0 -> 1261 bytes public/providers/mistral.png | Bin 2106 -> 2055 bytes public/providers/nebius.png | Bin 2335 -> 1743 bytes public/providers/perplexity.png | Bin 2108 -> 10678 bytes public/providers/playht.png | Bin 0 -> 23715 bytes public/providers/sdwebui.png | Bin 0 -> 2059 bytes public/providers/together.png | Bin 2024 -> 13884 bytes public/providers/xai.png | Bin 2651 -> 3168 bytes .../cli-tools/components/CodexToolCard.js | 64 +- .../cli-tools/components/OpenCodeToolCard.js | 79 +- .../media-providers/[kind]/[id]/page.js | 784 +++++++++++++++++- .../dashboard/media-providers/[kind]/page.js | 126 +-- .../dashboard/providers/[id]/page.js | 5 +- .../providers/components/ConnectionsCard.js | 2 +- .../providers/components/ModelsCard.js | 2 +- src/app/api/cli-tools/codex-settings/route.js | 11 +- .../api/cli-tools/opencode-settings/route.js | 19 +- .../tts/elevenlabs/voices/route.js | 71 ++ .../api/media-providers/tts/voices/route.js | 98 +++ src/app/api/models/test/route.js | 30 +- src/app/api/v1/audio/speech/route.js | 16 + src/shared/components/Header.js | 34 +- src/shared/components/Sidebar.js | 78 +- src/shared/constants/providers.js | 18 +- src/shared/constants/ttsProviders.js | 41 + src/sse/handlers/tts.js | 85 ++ 40 files changed, 1896 insertions(+), 147 deletions(-) create mode 100644 open-sse/handlers/ttsCore.js create mode 100644 public/providers/cartesia.png create mode 100644 public/providers/comfyui.png create mode 100644 public/providers/edge-tts.png create mode 100644 public/providers/elevenlabs.png create mode 100644 public/providers/google-tts.png create mode 100644 public/providers/huggingface.png create mode 100644 public/providers/local-device.png create mode 100644 public/providers/playht.png create mode 100644 public/providers/sdwebui.png create mode 100644 src/app/api/media-providers/tts/elevenlabs/voices/route.js create mode 100644 src/app/api/media-providers/tts/voices/route.js create mode 100644 src/app/api/v1/audio/speech/route.js create mode 100644 src/shared/constants/ttsProviders.js create mode 100644 src/sse/handlers/tts.js diff --git a/open-sse/config/providerModels.js b/open-sse/config/providerModels.js index d932d147..abfe6c50 100644 --- a/open-sse/config/providerModels.js +++ b/open-sse/config/providerModels.js @@ -212,6 +212,8 @@ export const PROVIDER_MODELS = { // Gemini 2.0 series (retiring June 1, 2026) { id: "gemini-2.0-flash", name: "Gemini 2.0 Flash" }, { id: "gemini-2.0-flash-lite", name: "Gemini 2.0 Flash Lite" }, + { id: "gemma-4-31b-it", name: "Gemma 4 31B IT" }, + // Embedding models { id: "gemini-embedding-2-preview", name: "Gemini Embedding 2 Preview", type: "embedding" }, { id: "gemini-embedding-001", name: "Gemini Embedding 001", type: "embedding" }, @@ -364,6 +366,63 @@ export const PROVIDER_MODELS = { { id: "qwen/qwen3-next-80b-a3b-instruct-maas", name: "Qwen3 Next 80B Instruct (Vertex)" }, { id: "zai-org/glm-5-maas", name: "GLM-5 (Vertex)" }, ], + + // Free/noAuth TTS providers + "local-device": [ + { id: "default", name: "System Default Voice", type: "tts" }, + ], + "google-tts": [ + { id: "en", name: "English", type: "tts" }, + { id: "vi", name: "Vietnamese", type: "tts" }, + { id: "zh-CN", name: "Chinese (Simplified)", type: "tts" }, + { id: "fr", name: "French", type: "tts" }, + { id: "de", name: "German", type: "tts" }, + { id: "ja", name: "Japanese", type: "tts" }, + { id: "ko", name: "Korean", type: "tts" }, + ], + // OpenAI TTS voices (hardcoded — no public API to list them) + // Used by ttsCore.js when provider = openai + "openai-tts-voices": [ + { id: "alloy", name: "Alloy", type: "tts" }, + { id: "ash", name: "Ash", type: "tts" }, + { id: "ballad", name: "Ballad", type: "tts" }, + { id: "cedar", name: "Cedar", type: "tts" }, + { id: "coral", name: "Coral", type: "tts" }, + { id: "echo", name: "Echo", type: "tts" }, + { id: "fable", name: "Fable", type: "tts" }, + { id: "marin", name: "Marin", type: "tts" }, + { id: "nova", name: "Nova", type: "tts" }, + { id: "onyx", name: "Onyx", type: "tts" }, + { id: "sage", name: "Sage", type: "tts" }, + { id: "shimmer", name: "Shimmer", type: "tts" }, + { id: "verse", name: "Verse", type: "tts" }, + ], + // OpenAI TTS models + "openai-tts-models": [ + { id: "gpt-4o-mini-tts", name: "GPT-4o Mini TTS", type: "tts" }, + { id: "tts-1-hd", name: "TTS-1 HD", type: "tts" }, + { id: "tts-1", name: "TTS-1", type: "tts" }, + ], + // ElevenLabs TTS models + "elevenlabs-tts-models": [ + { id: "eleven_flash_v2_5", name: "Flash v2.5 (Fastest)", type: "tts" }, + { id: "eleven_turbo_v2_5", name: "Turbo v2.5 (Fast)", type: "tts" }, + { id: "eleven_multilingual_v2", name: "Multilingual v2 (Quality)", type: "tts" }, + { id: "eleven_monolingual_v1", name: "Monolingual v1 (English)", type: "tts" }, + ], + "edge-tts": [ + { id: "en-US-AriaNeural", name: "Aria (en-US)", type: "tts" }, + { id: "en-US-GuyNeural", name: "Guy (en-US)", type: "tts" }, + { id: "en-GB-SoniaNeural", name: "Sonia (en-GB)", type: "tts" }, + { id: "vi-VN-HoaiMyNeural", name: "Hoai My (vi-VN)", type: "tts" }, + { id: "vi-VN-NamMinhNeural", name: "Nam Minh (vi-VN)", type: "tts" }, + { id: "zh-CN-XiaoxiaoNeural", name: "Xiaoxiao (zh-CN)", type: "tts" }, + { id: "zh-CN-YunxiNeural", name: "Yunxi (zh-CN)", type: "tts" }, + { id: "fr-FR-DeniseNeural", name: "Denise (fr-FR)", type: "tts" }, + { id: "de-DE-KatjaNeural", name: "Katja (de-DE)", type: "tts" }, + { id: "ja-JP-NanamiNeural", name: "Nanami (ja-JP)", type: "tts" }, + { id: "ko-KR-SunHiNeural", name: "SunHi (ko-KR)", type: "tts" }, + ], }; // Helper functions diff --git a/open-sse/handlers/ttsCore.js b/open-sse/handlers/ttsCore.js new file mode 100644 index 00000000..18c84705 --- /dev/null +++ b/open-sse/handlers/ttsCore.js @@ -0,0 +1,419 @@ +import { createErrorResult } from "../utils/error.js"; +import { HTTP_STATUS } from "../config/runtimeConfig.js"; +import { execFile } from "child_process"; +import { promisify } from "util"; +import { mkdtemp, readFile, rm } from "fs/promises"; +import { tmpdir } from "os"; +import { join } from "path"; + +const execFileAsync = promisify(execFile); + +// ── Response Formatter (DRY) ─────────────────────────────────── +function createTtsResponse(base64Audio, format, responseFormat) { + const audioBuffer = Buffer.from(base64Audio, "base64"); + + // JSON format: return base64 encoded audio + if (responseFormat === "json") { + return { + success: true, + response: new Response(JSON.stringify({ audio: base64Audio, format }), { + headers: { + "Content-Type": "application/json", + "Access-Control-Allow-Origin": "*", + }, + }), + }; + } + + // Binary format (default): return raw MP3 + return { + success: true, + response: new Response(audioBuffer, { + headers: { + "Content-Type": `audio/${format}`, + "Content-Length": String(audioBuffer.length), + "Access-Control-Allow-Origin": "*", + }, + }), + }; +} + +// ── Token cache per engine ───────────────────────────────────── +const cache = { + google: { token: null, tokenTime: 0 }, + bing: { token: null, tokenTime: 0 }, +}; + +const GOOGLE_REFRESH = 11 * 60 * 1000; +const BING_REFRESH = 5 * 60 * 1000; // conservative: token TTL is 1h but refresh early + +const UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"; +const SEC_CH_HEADERS = { + "sec-ch-ua": '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"', + "sec-ch-ua-arch": '"arm"', + "sec-ch-ua-bitness": '"64"', + "sec-ch-ua-full-version": '"146.0.7680.178"', + "sec-ch-ua-full-version-list": '"Chromium";v="146.0.7680.178", "Not-A.Brand";v="24.0.0.0", "Google Chrome";v="146.0.7680.178"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-model": '""', + "sec-ch-ua-platform": '"macOS"', + "sec-ch-ua-platform-version": '"15.1.0"', +}; + +// ── Google TTS ───────────────────────────────────────────────── +async function getGoogleToken() { + const now = Date.now(); + if (cache.google.token && now - cache.google.tokenTime < GOOGLE_REFRESH) { + return cache.google.token; + } + const res = await fetch("https://translate.google.com/", { + headers: { "User-Agent": UA }, + }); + if (!res.ok) throw new Error(`Google translate fetch failed: ${res.status}`); + const html = await res.text(); + const fSid = html.match(/"FdrFJe":"(.*?)"/)?.[ 1]; + const bl = html.match(/"cfb2h":"(.*?)"/)?.[ 1]; + if (!fSid || !bl) throw new Error("Failed to parse Google token"); + cache.google.token = { "f.sid": fSid, bl }; + cache.google.tokenTime = now; + return cache.google.token; +} + +let _googleIdx = 0; +async function googleTts(text, lang) { + const token = await getGoogleToken(); + const cleanText = text.replace(/[@^*()\\/\-_+=><"'\u201c\u201d\u3010\u3011]/g, " ").replaceAll(", ", ". "); + const rpcId = "jQ1olc"; + const reqId = (++_googleIdx * 100000) + Math.floor(1000 + Math.random() * 9000); + const query = new URLSearchParams({ + rpcids: rpcId, + "f.sid": token["f.sid"], + bl: token.bl, + hl: lang, + "soc-app": 1, "soc-platform": 1, "soc-device": 1, + _reqid: reqId, + rt: "c", + }); + const payload = [cleanText, lang, null, "undefined", [0]]; + const body = new URLSearchParams(); + body.append("f.req", JSON.stringify([[[rpcId, JSON.stringify(payload), null, "generic"]]])); + const res = await fetch(`https://translate.google.com/_/TranslateWebserverUi/data/batchexecute?${query}`, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded", "Referer": "https://translate.google.com/" }, + body: body.toString(), + }); + if (!res.ok) throw new Error(`Google TTS failed: ${res.status}`); + const data = await res.text(); + const split = JSON.parse(data.split("\n")[3]); + const base64 = JSON.parse(split[0][2])[0]; + if (!base64 || base64.length < 100) throw new Error("Google TTS returned empty audio"); + return base64; // base64 MP3 +} + +// ── Bing TTS ─────────────────────────────────────────────────── +async function getBingToken() { + const now = Date.now(); + if (cache.bing.token && now - cache.bing.tokenTime < BING_REFRESH) { + return cache.bing.token; + } + const res = await fetch("https://www.bing.com/translator", { + headers: { "User-Agent": UA, "Accept-Language": "vi,en-US;q=0.9,en;q=0.8" }, + }); + if (!res.ok) throw new Error(`Bing translator fetch failed: ${res.status}`); + const rawCookies = res.headers.getSetCookie?.() || []; + const cookie = rawCookies.map((c) => c.split(";")[0]).join("; "); + const html = await res.text(); + const match = html.match(/params_AbusePreventionHelper\s*=\s*\[([^,]+),([^,]+),/); + if (!match) throw new Error("Failed to parse Bing token"); + cache.bing.token = { key: match[1], token: match[2].replace(/"/g, ""), cookie }; + cache.bing.tokenTime = now; + return cache.bing.token; +} + +async function bingTtsRequest(text, voiceId, token) { + const parts = voiceId.split("-"); + const xmlLang = parts.slice(0, 2).join("-"); + const gender = voiceId.toLowerCase().includes("male") ? "Male" : "Female"; + const ssml = `${text}`; + const body = new URLSearchParams(); + body.append("ssml", ssml); + body.append("token", token.token); + body.append("key", token.key); + return fetch("https://www.bing.com/tfettts?isVertical=1&&IG=1&IID=translator.5023&SFX=1", { + method: "POST", + body: body.toString(), + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "*/*", + "Origin": "https://www.bing.com", + "Referer": "https://www.bing.com/translator", + "User-Agent": UA, + ...(token.cookie ? { "Cookie": token.cookie } : {}), + }, + }); +} + +async function bingTts(text, voiceId) { + let token = await getBingToken(); + let res = await bingTtsRequest(text, voiceId, token); + + // On 429/captcha: invalidate cache and retry once with fresh token + if (res.status === 429 || res.status === 403) { + cache.bing.token = null; + cache.bing.tokenTime = 0; + token = await getBingToken(); + res = await bingTtsRequest(text, voiceId, token); + } + + if (!res.ok) { + const body = await res.text().catch(() => ""); + throw new Error(`Bing TTS failed: ${res.status}${body ? " - " + body : ""}`); + } + const buf = await res.arrayBuffer(); + if (buf.byteLength < 1024) throw new Error("Bing TTS returned empty audio"); + return Buffer.from(buf).toString("base64"); // base64 MP3 +} + +// ── Local Device TTS (macOS `say` + ffmpeg) ─────────────────── +let _localVoicesCache = null; + +export async function fetchLocalDeviceVoices() { + if (_localVoicesCache) return _localVoicesCache; + try { + const { stdout } = await execFileAsync("say", ["-v", "?"]); + const voices = []; + for (const line of stdout.split("\n")) { + // Format: "Name locale # sample" + const m = line.match(/^([^\s].*?)\s{2,}([a-z]{2}_[A-Z]{2})/); + if (!m) continue; + const name = m[1].trim(); + const locale = m[2].trim(); // e.g. en_US + const lang = locale.split("_")[0]; + const country = locale.split("_")[1]; + voices.push({ id: name, name, locale, lang, country, gender: "" }); + } + _localVoicesCache = voices; + return voices; + } catch { + return []; + } +} + +async function localDeviceTts(text, voiceId) { + const dir = await mkdtemp(join(tmpdir(), "tts-")); + const aiffPath = join(dir, "out.aiff"); + const mp3Path = join(dir, "out.mp3"); + try { + const args = voiceId ? ["-v", voiceId, "-o", aiffPath, text] : ["-o", aiffPath, text]; + await execFileAsync("say", args); + await execFileAsync("ffmpeg", ["-y", "-i", aiffPath, "-codec:a", "libmp3lame", "-qscale:a", "4", mp3Path]); + const buf = await readFile(mp3Path); + return buf.toString("base64"); + } finally { + await rm(dir, { recursive: true, force: true }); + } +} + +// ── Voices list (Edge TTS public endpoint) ───────────────────── +let _voicesCache = null; +let _voicesCacheTime = 0; +const VOICES_TTL = 24 * 60 * 60 * 1000; + +export async function fetchEdgeTtsVoices() { + const now = Date.now(); + if (_voicesCache && now - _voicesCacheTime < VOICES_TTL) return _voicesCache; + const res = await fetch( + "https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4", + { headers: { "User-Agent": UA } } + ); + if (!res.ok) throw new Error(`Edge TTS voices fetch failed: ${res.status}`); + const voices = await res.json(); + _voicesCache = voices; + _voicesCacheTime = now; + return voices; +} + +// ── ElevenLabs TTS ───────────────────────────────────────────── +const _elevenlabsVoicesCache = new Map(); // Cache by API key + +export async function fetchElevenLabsVoices(apiKey) { + if (!apiKey) throw new Error("ElevenLabs API key required"); + + const now = Date.now(); + const cached = _elevenlabsVoicesCache.get(apiKey); + if (cached && now - cached.time < VOICES_TTL) { + return cached.voices; + } + + const res = await fetch("https://api.elevenlabs.io/v1/voices", { + headers: { + "xi-api-key": apiKey, + "Content-Type": "application/json", + }, + }); + + if (!res.ok) throw new Error(`ElevenLabs voices fetch failed: ${res.status}`); + const data = await res.json(); + // Normalize: add lang from labels.language for grouping + const voices = (data.voices || []).map((v) => ({ + ...v, + lang: v.labels?.language || "en", + })); + _elevenlabsVoicesCache.set(apiKey, { voices, time: now }); + return voices; +} + +async function elevenlabsTts(text, voiceId, apiKey, modelId = "eleven_flash_v2_5") { + const res = await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`, { + method: "POST", + headers: { + "xi-api-key": apiKey, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + text, + model_id: modelId, + voice_settings: { + stability: 0.5, + similarity_boost: 0.75, + }, + }), + }); + + if (!res.ok) { + const err = await res.json().catch(() => ({})); + throw new Error(err?.detail?.message || `ElevenLabs TTS failed: ${res.status}`); + } + + const buf = await res.arrayBuffer(); + if (buf.byteLength < 1024) throw new Error("ElevenLabs TTS returned empty audio"); + return Buffer.from(buf).toString("base64"); +} + +// ── Voice Fetcher Registry (DRY) ─────────────────────────────── +export const VOICE_FETCHERS = { + "edge-tts": fetchEdgeTtsVoices, + "local-device": fetchLocalDeviceVoices, + "elevenlabs": fetchElevenLabsVoices, + // google-tts: uses hardcoded language codes + // openai: uses hardcoded voices from providerModels.js +}; + +// ── OpenAI TTS ─────────────────────────────────────────────────────────────── +async function handleOpenAiTts({ model, input, credentials, responseFormat = "mp3" }) { + if (!credentials?.apiKey) { + return createErrorResult(HTTP_STATUS.UNAUTHORIZED, "No OpenAI API key configured"); + } + + // model format: "tts-model/voice" e.g. "tts-1/alloy" or "gpt-4o-mini-tts/nova" + let ttsModel = "gpt-4o-mini-tts"; + let voice = "alloy"; + if (model && model.includes("/")) { + const parts = model.split("/"); + if (parts.length === 2) { + [ttsModel, voice] = parts; + } + } else if (model) { + voice = model; + } + + const baseUrl = (credentials.baseUrl || "https://api.openai.com").replace(/\/+$/, ""); + const res = await fetch(`${baseUrl}/v1/audio/speech`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${credentials.apiKey}`, + }, + body: JSON.stringify({ model: ttsModel, voice, input }), + }); + + if (!res.ok) { + const err = await res.json().catch(() => ({})); + return createErrorResult(res.status, err?.error?.message || `OpenAI TTS failed: ${res.status}`); + } + + const buf = await res.arrayBuffer(); + const base64 = Buffer.from(buf).toString("base64"); + return createTtsResponse(base64, "mp3", responseFormat); +} + +// ── TTS Provider Registry (DRY) ──────────────────────────────── +const TTS_PROVIDERS = { + "google-tts": { + synthesize: async (text, model) => { + const base64 = await googleTts(text, model || "en"); + return { base64, format: "mp3" }; + }, + requiresCredentials: false, + }, + "edge-tts": { + synthesize: async (text, model) => { + const base64 = await bingTts(text, model || "vi-VN-HoaiMyNeural"); + return { base64, format: "mp3" }; + }, + requiresCredentials: false, + }, + "local-device": { + synthesize: async (text, model) => { + const base64 = await localDeviceTts(text, model); + return { base64, format: "mp3" }; + }, + requiresCredentials: false, + }, + "elevenlabs": { + synthesize: async (text, model, credentials) => { + if (!credentials?.apiKey) { + throw new Error("ElevenLabs API key required"); + } + // model format: "voice_id" or "model_id/voice_id" + let modelId = "eleven_flash_v2_5"; + let voiceId = model; + if (model && model.includes("/")) { + [modelId, voiceId] = model.split("/"); + } + const base64 = await elevenlabsTts(text, voiceId, credentials.apiKey, modelId); + return { base64, format: "mp3" }; + }, + requiresCredentials: true, + }, + "openai": { + synthesize: async (text, model, credentials, responseFormat) => { + return await handleOpenAiTts({ model, input: text, credentials, responseFormat }); + }, + requiresCredentials: true, + }, +}; + +// ── Core handler ─────────────────────────────────────────────── +/** + * Synthesize text to audio. + * @param {object} options + * @param {string} options.provider - "google-tts" | "edge-tts" | "local-device" | "openai" + * @param {string} options.model - voice/lang id + * @param {string} options.input - text to synthesize + * @param {object} [options.credentials] - required for openai + * @param {string} [options.responseFormat] - "mp3" (default) | "json" (base64) + * @returns {Promise<{success, response, status?, error?}>} + */ +export async function handleTtsCore({ provider, model, input, credentials, responseFormat = "mp3" }) { + if (!input?.trim()) { + return createErrorResult(HTTP_STATUS.BAD_REQUEST, "Missing required field: input"); + } + + const ttsProvider = TTS_PROVIDERS[provider]; + if (!ttsProvider) { + return createErrorResult(HTTP_STATUS.BAD_REQUEST, `Provider '${provider}' does not support TTS via this route.`); + } + + try { + const result = await ttsProvider.synthesize(input.trim(), model, credentials, responseFormat); + + // OpenAI returns full response object + if (result.success !== undefined) return result; + + // Other providers return { base64, format } + return createTtsResponse(result.base64, result.format, responseFormat); + } catch (err) { + return createErrorResult(HTTP_STATUS.BAD_GATEWAY, err.message || "TTS synthesis failed"); + } +} diff --git a/open-sse/services/model.js b/open-sse/services/model.js index d1a71570..66a45314 100644 --- a/open-sse/services/model.js +++ b/open-sse/services/model.js @@ -13,6 +13,8 @@ const ALIAS_TO_PROVIDER_ID = { kmc: "kimi-coding", cl: "cline", oc: "opencode", + // TTS providers + el: "elevenlabs", // API Key providers openai: "openai", anthropic: "anthropic", diff --git a/public/providers/cartesia.png b/public/providers/cartesia.png new file mode 100644 index 0000000000000000000000000000000000000000..45177c0902c7fba413be9b7326aa86ed4b792ca7 GIT binary patch literal 1711 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 JyBZs6%D=o<2ZI0r diff --git a/public/providers/cohere.png b/public/providers/cohere.png index 60a0fafe80f9805ecf2d4abd7edb9fb8719a85c6..47e7ab49ac562b415fb1a02478e21ccf0ddaab5e 100644 GIT binary patch literal 4366 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 RZMJd+4D<{!MLIUY{{a%MG|m73 diff --git a/public/providers/comfyui.png b/public/providers/comfyui.png new file mode 100644 index 0000000000000000000000000000000000000000..df8116bca480566ce7d16e648e3447177de1121c GIT binary patch literal 29834 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 literal 2393 zcmb_e`B&139{nPUg1e+3ZiMB&o@r7iQ!?Cgqq0}N1lN+u4XsQ?5g95qGs;{>Np!T_ zUTTY`xi?6T`(&vh3ZuD{yQPAtJ^ShX1Mi3Xx#!$_&gZAkx%ZQf_jXl;pZT2qg7A4?Nzv) znWS{Mef6Sc&PD6f_hniSMEuOD%0px5)+kP#6B?(DXCb_*$0iyuNLM@#0+us5%_-@s z)HgZ^lB#?`d9=l#a`}=ch3}JV2mHcQdYkQ{R|w@*-XD@rFtPq+F^MEAcg^w2%q7^} ziN~1}2owdUNvHM9qTdGPdd$8w?S00@&DxVSHz4HtqtXl%2)=8+c~AqG1# z{i2YHCCsHonw-z)iYVUZZC+evVa89cULvjw>q3~7`H@Z9S4%T2&KZg44m1^O8XB5V z3Gjh)yeRlo<*B}~S40xo8#8qqlGjsFUUiZbA+Y`JRtD!h>g>Y?S3-&=C?}j=GE`jI za=+I4Tv|EGTCbqjSaNb1j;JUzIRV+|%H4hOut9P&smd6<{)A&ZKcC0bX1k=rtp0eVE3p2?j656{P_dw!%A4Qs2eZ%3+HN zhBntV$V15(sTn#rQd!o?At4fLO^dOlBhfNABcFrn9gT<+3QQ@?!*V7pkbegaaRaIL zoOP42T6R_em(k>AjLW2uTbMM^87yP{z!^{`MU?{>qn#39l>oO@E|_*erNsWGFECA% zw#LHJ@I_80|JU_Fhx%APjdRbY$Zyr0#&;PDD+hNHM#h+S)L()Ieq+qks!V={G;9Fu zWSOLw@?(uU@yW+m=V5OamEJraZALVGG3j`1ZgfmZ;gfX2wt&(1=˜&4VMRsitr zjKR4fbRE^SPFQ)Zpk!9T%07+?;!A8xEYA9Q-}&xhdx5^H@BICQ@Z$&aK<#;mt;X>H zV0hWWl3h+L1%iQs*ZGw3P80r630oNT*RKyE7+VWanX&nh5N^T)zeQe{ z@~^+p!m8UQ2pt9A_g2ISHBCkg=te(-P0i9+ zpKF_MN>~^WLEw(#^|YKno|Mx_5U#m7d7R2qXDDBi6$9d51Skj^k@7qiQBZ>!;tPr{?*VgIdQ3IP-! zm6dU$*@H6MC&SQT=Uk=-Y}1TiHO`HAfLG~@q(1Gv;64kqQj%2T)f;OD!b*ckStlY= zcq?H|B6dCRn;UKHBGeBV-AN3iz1>rdrhSw*9sJ$(s6bvwNr~wc^#9yGsVS_EE@j)q zOMeWXbf2M4@I^&nfmLk({&5KOoV_tMel8~_So%j423FbYgPGb_iCVI|?l*45D- z5&iRIe$@0cAtHcqhxkFg_?_sRN8r1@H+C<(ki~o>-|HNplmrwF2Ke1s9CzqanaHgJ zwMi_W%X^H{DSn_vuVdAmsDO)fi14N$0M^35K-|WFo!P-cE#~h1Te01(Uo?8!Mjb2{%&hGF#+V?RxdjV^+%37ej@J9A}j+W8+mr|B{}bNmi~ImI6QcIb3~=E z3iGosaDXt%zbNQfIm3An!A!Z!?@`)N3FWdwQoA`#UBlFmr;Q;Jwd@z z4}PZQ(?V5^4A38C(x7e)sr!<{zEq}q$N>FWIs@wV@6KSUo>+7kh`X}+4Eet-m2--e zB^Vw=+h~(0ws_vMI;i_BoJXty*v&q;Vr{Yts@W9JjY|hUl|$tx1Ter{QCgV zUL$k4$s3O??M>xoqD@d*F~Jo}8mg&RhSPX)FSz$1-TwmJ{n2}m3{9~Qv>9C8itsm0 z&!+SOl#xdmT%~k5U${%C`GUfi3^m8-<3sbm#DETWq&^-J7Chh#7Aie4ioBPh;#;rp z_&y)ys}=;=Xt_?_y(I06lI1O1HZ8h#HEOWTo55AO@GIl}cf{zwY}<7V-)nkiU%?vR z(%G+aO+i*R{qKxhF07JFf)U~5so}Jh^E`{R#nrnmpOlzP=-mnQ7PPyIWa#itQL&Hx zWLi13mqdC~83cigu*OH?u9G5^1xIsD=W^s9%`lseG#K`pUuAVl&)P$m_GDuhnpvlZ S$IAA9CBWU;8&~5LNdGSqX=~E} diff --git a/public/providers/edge-tts.png b/public/providers/edge-tts.png new file mode 100644 index 0000000000000000000000000000000000000000..8b1b333f4d09dda73510e5cf07e207e1aced6f32 GIT binary patch literal 1348 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSjKx9jP7LeL$-D$|DpDgn(|mmy zw18|51{Ovs23C*~Ahu(ahO^xmH5iz|;!F$-?U@WLP&Ix)8Uzx67^DY6GcRC-ss@TJ zV1lb|Sip>6164CjiMi7bq&N#aB8wRq_>O=u<5X=vX$A(CR8JSjkP61Pb8WLl0!7-+ z@3r>q`O&H|t_tfsT z-VJBmtq#uoE@_nbJ9ClaV;Uz-G|E$dkapT*P)rps*_A;=P*>9y_0x zKKg5)Dc`hP*LQ7B-~8=X$h-INqwXHRwEJM?=ly&4{@T*<^46l4U9Wz-CP$p!pct`Y z_OpLK)8EIhkNe#Gd|Rl??f#4BA~ydzaU$P+|G$*@)AP4|&bZBY%fz)hvC@A3r^$CM zL?3@GviiM$&E^-HKLXo}bKeEr-c^2YZDiu?OeaPTxrSYv-YZ(hpT8*I@TXZZbZNK7 zY`@@de`XcxJY_qPUe=dW*r^f>qunOPhvJ{wyxDlj}^ zJMuA;fk`3HL1sSN5a8BVr1W%0@A>9d|qF?s$qGV9qF8JG0h_Fhk>)-+xfK_hSjgy z`%<3kp8NA=u9e-FHUDewa_h4{&{$ilXR`m(SyNZ*+m$(IxMynRKa}6ccd~%t({cCz z{U<-YvB_P-eZ2l-TC?c;Gv}tA*Obkiq4B)g`33`{z`Z{`eheH9I~WUVq#77Hqy>&I zXB+}t`^*%dm~+=p8keaR%be#~HS6(BLs^6LcWZj96+bUYTs4`=VEeLfn`fTm*lJ^J zwKU=2a+dA=hn~L*`F3;v^*XY{M(sVH{aX6` z-#uHW>y@!<{*KxEG-GSlkE=#!lvI6-E$sR$z z3=CCjKy@t)48K6?UobF~8Za=tN?>5Hn!&&zUNC1@pbb#MB{jk`&DWPf3&`eRU~JE1 zU;(lifmjNN85o!sFfuR$X-1IP0w%a@!vbam8>G;qkENV}f$4##i(^OyDs;9BUb*dx$0bP$&*Y^cQZ Uug~&pn+i(vp00i_>zopr06pqFwEzGB literal 0 HcmV?d00001 diff --git a/public/providers/fireworks.png b/public/providers/fireworks.png index f7233caac7a1a0580e724980c917691e330cbaec..2295c0c7d3575399c2ea4b379c658ee89b1f81e8 100644 GIT binary patch literal 1729 zcmdT_c{J1s9RJPX8fIl4X(i)HiQ$blFD;sb(YTXiX=`#+gtf^vLygd3U)ibQm7D6j2F=!sO0HSDh9%7f9DW)cfd^HRRK^&7y#XjD4?eR06>aC z07Rjn&0R70?<=(!^387sovuU40HBO=Cg6P%K(q9Qv-*zPTFLQeQ{+tR4erDOvq1-liG3*wZVaNW@J1}FUf zTBs~6xcX@)NLLxID^Zsug43T0QS(y~vHJ11If+*fV|R1czRV9EkVOrCf@cV$nkTr= zRwgrxJjO$*Y3b;W#~D3_LTn~_HqUP7xOcM2MzVFGZMT`gKnkYY>P7fGV0k0>Bn+n1b zr$Jn!|O55MW>#%%XSONE>i>qkKxJT3ff(gA%B*pri2# zbSyOA=Lk42O2|J77VmRs?EyKn#dGE$>7Cuazfp~kOUXB>>uxv9TyTiWbz4_lYN@l% zE<-gxIenKQwvU;G$hnBx;30B~!n_>SoSJ^8jQbP2l4@fdh~(@qyiVdfqqZT$Li9^- zib<_bgLNI`YJB!h=Ja_CVC{RYjHt<}lf*S(hHlp{B=%>169nDv%zMB6&nlQNZrWj!^kq2UX$%RemRR5{fQdtN*duI_tW2aH=pb%WrXuG^}_Go z6{76MX7^78hfH2c+x~Oj4tS8h57`@2p>0{8gx+EmH_-DPT_*K=*6@Czf|J%|>R9dB z)Xx6!sU;fnG|Bc&E=KYt`}M)7%4{fE6o+SK-uo#mCyE}&ABVd3f`&2WgHOX~{rZOXNF z_YZC2{8+pEye~I^oUwe2L50q1Jb)o^g3)FKcOTQt3AjYlbOpL|ScV{N48|N}=fFyb zdakZk|Jz{Hi{T5LUlV!<`nA;YB4_D*PM9ykLMXKWLCY+arl0bbPJ&(h=ICc@l%KhC zPlb!lWE{OEY(K1N(zu}&Ir9iN)+yN1%_?ZT2>Lp${v4I{ir@NLBcZopO?&1ADi}jx z*EDgY^W{ku=z5mjhaTEoa$>?9p1s#NrMW?M`DFtNNjbA7r&P~%0DC?NWrmUe=SVlC4Wy?+G#M;m{uXIwW}uIv|h V?}rcQO6AS>;q2%^sI(7E{}Zz!48#Bc literal 2612 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 A7ytkO literal 0 HcmV?d00001 diff --git a/public/providers/groq.png b/public/providers/groq.png index b6bb68a13035d58202bba9d452f1552190b5dfac..1773fb66066553550648f125a6c4197ce02c8af4 100644 GIT binary patch literal 4915 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 literal 2882 zcmb`J`#;l<7sub*7{=t1`!%^s$-U+>m&~2qQej95g-DdkHY1nhe#s^BaVvLS+|4Fr zDf6w5ORg)ch4iuITAO`+{($dq-ydG*{BRzRbNS&sUe63yXA~SJ4FdoGZf9%lc9^mM ziWhnqUz-JtA11y?+l$cvz%Tl*KtNfABmls+?5r(3;wm|5{ph#Qj_k<(Gad~MYy3v_@B=%e1^6vKPALCfJXVNL3hFZze zH(rKp8iurM*ZZSt{ppT)dL0!>wu+t{IfkG|XD&$hzZXe38ddp0N-o(~Mem2R`{sbXXJ=)(cvypHpw{`qsMLJL@FMyh9|D8nmGQzq#j*ettUP2 z<#8nAvlQz{;zTDl;gUN8Q3mzVg5Swar<;x>@W_$~o}!Gpyzu&l%3Wg6OKs!LSNh%R4hel7)m2BE z@niIXw^-wxb=hgoygj4(Yp+&FCnY}m=bNtyPe6{OZ=-;6-P2$d>Wh<{C55?3iP%D0 zU}+uAeXSl-OTYXvXyc{ zfyflc>u%gazt1T`hOxY*leI9#tp`YGI!IWz+D;7lT>>W{1W^jIEYSS_4p7H)#oP1K zyxyg;dJU+AUaZ#OG~XY*5d(K;cl4 zec9Q;-nu~9on|j}dCZ`y(82(MC~aho=;|;+wr(VC28oACEd?v!Wv5+*vsq<^K$q)f zSvfkf)Z7#ChM|vCh3{{NJ(17D+>5#Tr7f}lq;W5i*87d8cR#xvw5DQql`7#vmcU8JDdOd=Ttv4dCmo0!TpK3Nb>^1SQPt-mmLcz zTwVL!fw>ffVVVy0iG!aVS}-9|Wg6Ijg*l(^o8SiraWFpkx{KcSLUdtN^M0^`QzZyiJ`L3iyo{^8T$4mqAbXWfZ@dO~ z#5K4;Ej5xh{kB)+&UlAlhrSJ}O#<^q+yzN%DbG(SIzBb@?WdUYk49a`Y_GhpEmA8_ z#YEUwf)-5Y@pk5Sj4wfg@Fm!vGJT=CelBIC<&NNZFuXn5p&evqBHaR-sNxr=QgDX=lWIg2Px)@waTrkBt4C~^;bKuJuu$s#0x|=I<`SaI@WIbSKhug+X;u$FO zjUdm#<6Q>IGe_)5S|N0H@5W*4Z?V<6)&|z+eeqE{KDy9x5$$`hO^oA zXPK>J8+R82U?RyA=WBXi68U?c^ry(Xom=~FN%UURy{z?V*c~4Xe9${119aJTaA{_6zMPnS5#G`VqK%QLj}bM)$=)pt zt8r0I$(6z;5rO`m+9J#bRK4cPXpZGl1l;}3*Pssv8|9Nwp@n}=oD_>Yo6d$<*t9nY zrm^lf*rPRX`L+jVsX}g>_HZ7=e4;kYksGlZZ{NOPS=yyWS;O$BbuX}+yE%DgKnH4Ml5bVNn{?}|X5;yJ_%t!1x zy%Qx#1v77@Vjo-86$hg$>#pP|_!*9jy5Bg~B<=7^F;bkuj5u9%Y0h^Vh)|eJf;^>5 zQFR-zag-y7>kMdHm6k-zHp^7!BcQrXVmpH(m$@77I@>=b_X0No2a z%O70GYO(4+o9*D^D;Xl9zUH8l`9Q+A=;HfRrTL&O^VR1(YX95wtcT$K(k2ZuTq-j| zIF0Utd?>;JyjfeeDd2^zISp89-1Y$OaA^_6MX+igvC!odu_sOlA^S-WP;tWv5-JZc z$y0sFB~$st%#ga*82Wh;ob2 z??OK`-6IREsTn#-p%2SqWr!F!Z>Nuuj=j7X&k?jTfg>$BH(AmMxM2A%HXMRh&oJOy zU}1MsPYM=`gpzR~?Ke;# zv0+7DVktaj-lO`D9F#Ww0<6*F^|#$Geu*td)~c;RoykoS=tzqGY>LMt9r$!8%uDfD z93_znH`6HGTPz|{!6kydJXT~a8aBqmX9qtdReYe@A{a+GT}_(1rCZf_l}II_^OQ^< zH-d5^$PzyGcx`O)daL7<*1Lb9#((_!Ozs=IxR3gKABb{bJ=-ew0`k9 a_7U3X;nUyrwmXDk!0w#0b*rU+@_zvlO;hXu diff --git a/public/providers/huggingface.png b/public/providers/huggingface.png new file mode 100644 index 0000000000000000000000000000000000000000..9a36b8f6a346c1b244cb95294d76454875cfa7b7 GIT binary patch literal 15383 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 bzHgW~A#)d)ualAgk#eQP z-HqEY5QJqTW!-z!K-@!IK}tvkP7l5YsQ2sZ0s+xMR`f%P+}$B}1~8JB#5CvI;g2Zk z(lxH{KYo7Z{QKek&!uZv&HT7rqrHMr?T^qlyj38oYBZYZEx=GkLu)aKirUXgp>b zs3ZW*$L%w50BAmT--*Qxjjv-!5J>=Wnv> z12|U_0IYs|rFs+%0L`yQDPD01aIPo-SpD@W*0VzZX#T#!^U5&{XWdCLSaP>9 zcbx#%X2hg`^hD4-00H=Hzs5YkJpgFZ-V`DL-D~7)CxZ2okN`Lr?1><41>m`Wq?iEC zMF5X3Q($p4tkV_&aDFu0JpeuMxUX?t;A;K; zde2aVxMOKwmw-#(CpdcVJ^{QZk!t|@olciF1m)U;YXDF*!M3VE-%^8kBkE&b+RyGnqZO6~dOsP5?q+rxJZ%WC$Px`YP4u#pVEnKu;z6 zy67a35Xh@^9~WN*5CS<#^sUG;kPy_e9LK^Q79eo{3JMTcRi$n?3YY%~H8L#2i<)x?jG1Y>B#=q>#P X9;!U5C#yt z4%^!m!v9I3Ld1XjJ&=40843VTfVrvBxiHwgQ+JxwNwFBsPjuaZN)MG6e$s2Jrn=&j%*VWY+nT%{c z@0m-q>kIlE)YofQ?2;Y6^(~UM(d02@6MS-JX<6X$;ZEq|)#99+(s9-#+2@(+hzGah z&E`ze#BoIk;Gs4NvR>4Cusib0NgH?o6h44kM99$Oz|m`5mm`|*Yays+kABP2Mo^P8 zRO9{!lhFXk%zsA`08TE5Yh!kk4|fsA$2=oMdCBJy5>Cv|P#qVv4?nr-X6OHLV4AJA zBVV<9%m2`C_yJ6Ak9XrHUjXOr7wFP9=u^V7w!>}Hh=ktTEi{VacaOffIWL=<+QATY zciLAyY`;eI0H)FGeZKiU$KtMcxy5%mHCS?%v#!bO>hHA);>vUS`RO4~msaV;mIYHr z?=|8W+v5ADoe4N!TK~1z9HCee^OsR3s*oA_A&ZCV`^V6c!O;v;#2@z^+6^!B>$gWO zAJiQl8A`c+E4X9I2vz95E%@9PrF554`djO$R*VG8{S+%r4LQfJ53RA($Br)j3n1Bv z{b2>hVByO}NPsTqA9Pvt-R`wr^GOEv8P>>2F^wOr7Xf&lx}T zKm6KXi;`PQzLn(=6QXC^R}qz50d?A7cvv~u#3k4YS}`tyxmcx*CDq1?T4AusDJ?Z+ zk(OCOLw93;>CJRrFzDi+y;vk%HX&aY_)W?2vu}u05#t?=ua-y_JOT=IQ*v@uAui&g2q zeegWO5bPEg44HS^+c-5;rR7dZ!HVP*=4Uib*zpl1l@d8Jt&L%5Z25s4NNhABJ-+h? z!@+Y>|MzFXfonGXaE#vyS5Z1m`PIsaQE;ktOqu(w$`}n^!HI6YXyv45kzRw9(@%Jf zuUK!ifN}=aW!@g623I#o1%aj5PJTH9J>);n3IZaY_=O*82qK_rWQMJd-M(RMVTun1 z2KYl@szitIq_XiGy!zsp6C>6!*Shb(8|qYKNUPv_v8wa)+R2YJoe=pCA~KsUpX5m4 z>BKN`;kse+sN40f^mAa!p^davx&B{v?5M-+Hio!(|lybD{*91WotSd z*IXMRYm}t?^LW|Dx>;}d!V6k_xt)lts(FuAX#A|=aZ0mz`_2JncqZrL7jG$sb!U;g zV)f8|VmLpgWQ1{ivIDo^MCiyoObd)w_sR}iX}!8wGNwQ!Bwra6mnUJYqg0;WW^mOS zfyq_w`=us+Ju)%eT4ay(Dm;X(?ZW}9?nen{dsv9s_>7vl`SA7AWQ8Xu2$f?R_&N@W0dqG&Op5n7H z*YHxGpUoBTLc1n1A-Hj5OOj*wSoS_WZX{09QQ7B7y{+HRiF=}~=ak9zXURxwk1${kv@&gVAOP)14v3LeO>)@6%k4A_e< z;7BpQ_!uWvy(FxK(;9A0$8HkWx~D5A>JV!6R-Yd_F3N(ctnOD^YJWb8ano~1tFCvB z&QE2dO}8ClqgxSmcT8;@TN_vN!Z8Az<&2-o%yS=P5Dzq27RWe zuv5m7AekF5JII^7lUp*YLtl$v&igNMt>zB60(joDC>=8dOxs$^QJe^B@0^+T!UNBD z9CRaQe-73Y0kd$G57eQO(emM}UbHqnt%@WxH| zMVgCS+dP??w=se_l90PYTSRsYzLc{a7WK#UG}P_unaCdGCxRCW=|eCiI&}L=Q8Kt< zjcq`n@SM#)k`S!7^r$ZnnmD{xadVXQuw}4^?SkXKyjEYPZ6JWf7O8O8Z0aC;Flz_X z(=s4*P0u0jsC_;FVuNs@wQLCFvni*v_+ zlJ(2rI>sy3wRsfE0ERC~6Z_#Q1e+Mh7{r9#Y*#{}Ddn3W5p4dz-LymD^Utlpcwwt! vnz(8-@mSd+LJakCNk9N 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 B7x(}G diff --git a/public/providers/perplexity.png b/public/providers/perplexity.png index 4e9d56fab25c1b52c352fa22d3361096f1dbbde9..0b5851e5f6d089656ee1130741fc834197a368f8 100644 GIT binary patch literal 10678 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 LDPJ#V8Tx+!Sh%H` literal 2108 zcmd5;`#;nBAAirrY$Zb_VvXb$!bvBW@v)pT+ZVYWm(Won6~dW9W=3>X>9{MA=3eeG z=TM?zwnT0@y0C`XhD^DB=kfg~zCS!)&*$U$d_5ko-(Ig*nzQ3EIkYMo03b)Sw{wv& zbrZ5OlKRs6WVeJ+;r3pU0Blj(1PtWl?E(NPAlliw#pKQA`kZt7O|6ri^r=OQ=3wFK zz5S9%QPDrX4_PEbPsNx8yD>H7ukn(4>gwp-t3GIt5KRX};lqmxdKI#oxW+!hb!Yv9 z7w?l2p#yz=HGx5~3eQ@`#sq>qLEOeftX1~Z(wf*NGRP5s0QRcmqXwB{r|qtAPrt3$ zqEq_BNy6Bty9ezeVlnfa7`=gKj$t>ulx}=0U^P=dys-7<#FEP{BFG-NGc<8TX-SrW z%g(rlEPMtkhyD2MQPIS0fi@$JU1qw{n%5CvS4?NPsWJbrbVHCMHU zB4nWDc^k@>hero{+jJOHHp=!~5B72~F5f}kwD|J3aq;c_CuUWtZQ#a}4J8^*<{IYHSozM_~^+00V&uZ946(m63b?Vj47(g5(}? zg}0qXK#qjhS_83Um-5*(=oAtZdiPx2BMUXpz(BhA2msc`G)w&`5MqM>pWu6&iU`R6 zGaH{Jn(q@Xj+TEo_SiGC`W-u=-o>V#7rMs#$X-6h8+x_>5q4>DN9f`flE>5&(qGeE z{hBi;OWcu+))-=!&zb5&yqdiUJjy?7$K@ZG+muAW&APr|8~-l#3j0~)n83VJi!~2T zjF!)r{v>v`_Eok=fkux&Qn`oEpVJk2QZs%Qa*$``#u}ry*O06NPSgu0RMt3rr^=Nn zD^TL0{sTV=vPL4mMD>sqfPFZUr(b)CWClvO=Z8b^{5mhGw@-AkUybv5(pMwY(i z0Hu~Ku;2<#MA@#eCT3)ky(M@RO{zW;EcMiA-^=R9^g zw5n#3`sjR%5*i5mNu+HR3J51&J~o#2ls)Lj zXxvP9-S@zvSD0Rn_oUnStkJy%#3Av33b;n$-)zbz?F5o3=#@B$qo;o0AGIzkjWfIx2 zPnxQ8J=4zW`j4Q5`_caIvD8M7^@q9MK6|A^c5`>>aAQHYOMF$K$(JVX@=!x{2(0a! z<qG zH0>tW;ZS-2=(!sx&^@;@WdJH?XLB0XcUoX?1$~5Qph;zGO0VY8i5*@`eMF$@?M;AL z{T&cN{wlL9OEsUJ88H|U8=r?A_Dk>*R#*;K&UQJ`1>8)2Wxx6E1XQa^M+;X*69iZv zYK`{Y8!4)-U^;x;_+EZxZblflah<}|GWL^Rj!_&MM*uDG)KS9%6v6{gI0M)a93uup z2*pE*F!sG7)eK#6_%flo~Ak9>%ov)+KTob<^&G+n$!8Y9gRp z1O{3TDDj;TUpy?J_65J7_0@J?29AJhgtqGk*DR4uY*#9rWcx}Np;>YBHIkV$EZr4j zY8ys@hYKr`lbRlCkKUu{nqg(nnr2hroMCCS0(cH9bbi~?n!qdM7j2Ma<&N(!OKDpDc_^o0FtGGERp$6l`JK%3N|M3Nq z8GLP$v&+cMlJM|5cy~&#zxH_Yc~gi-ONb zidf`yHOcWf;C26wXSlqw8`bs5{A~+Cgf1WDZ~E3(`xN?eCTb)}h(lt zNkKPv*LuC|V75GW`)X;F(SKCC|M)_^iM6>fmZOd>>&`E@!2ce@oU>9GUW5B;E(G&d SWi%x303iP6XjerDp#2vbqQYMQ diff --git a/public/providers/playht.png b/public/providers/playht.png new file mode 100644 index 0000000000000000000000000000000000000000..1807e9a2b627f7d078e23f2ef94abf74caba170b GIT binary patch literal 23715 zcmV*5Ky<%}P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91fS>~a1ONa40RR91fB*mh07#AmcK`rD07*naRCodGy$75mS9S1Pv2&a} zvpFa2u67krA_xf~0RjX_0-h`(llg3HKsY?$nP9-i27_&kKNE}rkuw4%kT60bD6Ych zIJ=WW=Tu!?_5SBp&+P2%%vxYS+u!fGwzs?L)(z*Le9sM|`@XOJ&-Gu20pq`}>Hle2 zFz`PF_%G&z-WW)aU;vdW>#9&7MBpoYrs30J^SIgfGWw8isCJ_HSCl z|FQYo=29Wx-{?eOSf5T#{plHD=qY#~96WmOz4t!)=%dGv4_2#HLpOSQd(S`r{41|~ z!KziO{tcl1=k-Duc)A4m$xnXrjcon){!$`4~780RmJ`OiaA*eSh}tZ-1-dIN?yp^Zax=-QVArPG{U!Yj|jA zXm|)i;5g2eS6=yrFMKf+3JGzZj`+<7=0E$H4o*%?bocbAp3=HV`G59B+h@3jhlj4Y z<|Ua-a$rf{k|q7!-JRE7`|^Va50oqAR;%T@?(p#Nm%jAHXFcnZ-rg?We&GwBr#25N z{hx4s{_~&Pv}yeZKJdO~)A_H088>EuD}d(Mv7^s^_9dNN+1}pnfdL^vS69dPzV}^K zAV6^&(R=pnUbk)yZ+GrIdwhIswnpkvRRx|>@ICu-!JDU(XR(5_>HkJ03MBu)f&FXO ztxl(t&wlnZtJTVE;hCESD_Jmcro^0I)$jJ#+~mMxoRi`&>W0>8wOihK%i~Wxf!}rR zdFQTKy{g%4W-^&=Tek*6I^%tcTeflIrYo+vf_hO%d-m>`$w0zpK+&Y1HQ zJuzEsPP_BGz&0ea8MyiMr~hekV$!nAn{K)(8jX=-Zlyt;r^3)~XKuDd?%U1Hc3)*% zxcI^ZK!bnri(mNZz4w}idCfJ~yy=Z^Ix##90j|FK>J=;Tb_7;kH~1*MDUTaAZ18*! zwKO$38GuD4hFoTlb58!?{psIQg3swM&YVIqRj{qWXDV4#p##&ee)UUy3ez+%y6EET zu6reznrE{Xs^sZ|7j#_p9#_3x^}@yH_g1l8ol7JW zue|b$-t+`=kwuk=q+z~ zOFSN*>D1G!>}ll+P_zJ|=9QjL0A6ESKlZVYj*gB}`j%VXiICoL#~l#z{PWH~d&iDb zrBX}?#5gf@;>SPvv1uATJw1rRyf*%uJ?bMP!}r{C54^H&-TG%e>)8st--c2CL;7_J z0l+5Q_uzxS`qsC;MeUbgcKI9M_~vhX;~Tg-wjH|h#+z_4XH}(=6><5oHGlK5kBtnE zaC7ao*DhPOTv6rB;LZ1xRBlmazxAb5>`A*f!zd(UQQ9>JH=p?1PaHaQ2*q&24L8JM zaaHi&)%2+_ON*zbobf4We(v{Q{q;w(*%Us{Pk(wZ>DOO>Z8n=e=bRl=(^FKZvE!tXYM} zeA#7}*6Ovnul_yvhYufm)vK=m(?9*=dcE#>r?hzHYUjs-%BA8RxBmzWyLt2Gi!Z+9 z(BXr-cI|?K+qP}%$aa8R6uly-UMv=W_`};i``J%F{`eCps7yNjSAX?aE0(X2Jo7Bt z91Z{)p2)z6`p!G=Jb3URDbIP%bDn$YbE$Z4!62t3wp)~1NaP~hsX1xUXnC#se)hA6 z9(s_Gs^0J>c>C+G1$MmyW<<*{CbedaT*8q@B7Dp{1omp>0R9&nQUt7*3I|b z_p_N=&cw@#JG}3H_uCgz8JVw|`x?2`zbW8udem4nFzh<4Od5 z(($$CWgZ$j@rF0N4#=g#Oez+Oy!p*<1i57U(T{FRr4s2(GTV{n)7#g*WNAO+N*d*n z)_L30)A`VYza}%_onATVB+e1*lO3Fuu-Cu-wH>N**jK?uo|D;B%EDjsCE%{R?rJog zL?V9GRWGPjYv23c_i(0A>%Bd_-~ayio_z929JoDu_Dtud@kME)ySwMY3om@@@BhJ$ zojZXZ%XYehbSfw4_*WnP@Q3Lr9G6TcTAo)fm4EPq@4xC*xL7A`l4)A`eD2%d;orCR z?b{DF`}_M}_qx|#cinaIcw(kbVOBtT$2;B*R0v`$9t+tvk=h^p;0LdN{p)w^IERqQ z>eZ_V9m2WgN=3l-{8%)q$3)_&2S~a)yJGP;_W(c|p~n6D_hb1=r4oX&Wy_ZBXP;fK z)*gK5!JgipjT<)2v@X9?i%9L=yC)P1Lnpl3%PxN&p3B@kXS$!Ei;#;B!8oKoQdYB2y%Y*v!Che%EEE0 zSFil*zy8Q0k35VdWwPljuY4Zy05ZT+iuZj+*H>I|85{~c!o1m(NLwcP_P75bC<}6u z9W^mg&RWJw=w0V-Vv z39HwvcixUxr8?+;^Y7mD&2N4K4GX5|YJXqP#*OPf{NWG6eT*19QI2R4J|{0;%>^;I z#~8l)RT#z$TKJ#->3@^>lb`(fdC$9yUP0Z@e(p0W8wEYs5Zc4|aMK_B!S55a32MO5 zfoP&P-}=@!gOoe(x&r}4GA_UTQn+|(Y6{b}e7W$@%{RY>7H4%jVgZ>!B>_0f3Y7&& zfjPhwO7+@nUjgO7{<-Jw{QFP--7kLe033sE+_Y&!|3F{=KrdMS*vI}_ahsH*9_R`? zf|jLA`{@p70c_;^jyq;8K>(?I2Ut4!tnN-Bz}w&cHlWO8-3VyV{#JdP*N}hY$YInDuwHxJE1>S5{n>j2cU@U*Ce$VL zM4y6!-~8s+X&OXaamD48N|}nl5n?epIdSFlpGUm!v0aam2>D<2>Q~ZXnElQ>@8EOM zMbCgj@E{8FL1k0}v zE3do)BERWPZ=i2T++GFEY<2(gFQ11a=nR4aJ19>>y1@V0YaRher|sMC_z~SeQ9kpT z7h^w^-pJyRyz`y!C>8`M3Ryk@@Jla!7H>f!JV?5#9Eim8!Aij#+;AN~evFX^^0Z;Y zx~r~wz9Oessmm_A^xk{#A%l=j@hJm)(diwT_q^xbqzCZK+z4!N8}%S?J9lpXY-D6nwBE51(>03IZ)kGuAJzxNhQ*6P(OfcSTBzDbn_%Gr;Puf28a76gq9Kls7- zs3pM8Y^8H=6!QI2xpduiuK){6mkvNV#cSxw=ihbLoimvQ5%BwqU;IMYpPEr7q|CG~ zx9TI=1GL_I?@#DI6@nd92SwJeU;F;|y_X;ld1kTy_kaHhv5kG*TefTp)OUapzFkFB zf-X1$G`eir66&NZI0{~&>(Ktny7q40e%A2FP*5}9@4V&hcm&`YeT6+IB>?X$U%8cT z!l2*!);Cn5bb-;?Ti^Qo_`5)|>+xNZHNeYU0-!*5o^v)D_WkdFFRV>}0Q!61`;Mwb zIALaP}RMYOmO({Au54qk)ahUmYsM0IY`p1wP?D{fJks0XhnTf zEsUiqq`g@u%4dLf^^0E!%J?Wp09kJL@u7zvLbmAUvZVvOg@JfQwR}GJxldCkEVy~| z2G~(`xXmA!PZ5i*?5($caRw3Id*1Udy3YscKXKy3+bY0@F)%o^^pcmn2!9z&1$|ao1sWw59yQ!};|*9vSQWIcS+f$wLKlM?Tkx7I zx`oyQYsL_XKJVDM9gRP?)qnu58e8G`@7S?TC<oBfZ1@rFHV-YGX%L{*zxP2R=w5 zDvS{dTKL%DF~%cTzv${%EDpq{jw9NE!$17Pw_Seu<&0~XsmHZoJi?%4ZcYYexT^o_ zf4$}Q+i$mR8!<%TG4f~d#o$f_%Y4JM7>+&u_^vm+;q{L^`Uvq<&_gBRP?+%F+}hN= zZdw+kdfVIoaB%QA1!Yjx@{$C~6G^m=s#B*<#**)O_q+b`BOgH&)PT`XrP8ZcucZ>; z1Ta1a4jg#X8{csF$dPa)f`wC$BiNL48KnxzF!9^8b%f$}IHEbY;wM|cYXX7kM6s6>wp=bg6`f}g#8>p|r#2I)aI ztQqzY&f@dZm%jKN?|2)GL*`F>;%{c_Idu5YyWjmT{94>0xC}4gy6ay-e$>>Vg9ph* zg|j*ega4V&ei{P~H^G}PeBqTVSFJ#Izx1V7=X1HB&RVVdY`e1gv9mJhiC`S7GjAxu%QewpD;o^%gP$Jt;BxcvH$HW|VW*CcrP1GIL z0x(V|&OQnU|5d>$GJVG#x8qgQk$1i8|0ZUG=0QUMEkng1vN=ad1h9w^Zi~-HKl)cR zgSav9qs+@*_R@A1`3drz{01+9HOHezS%JQnz3e5$89jhG`OCljaNu-esX#0G9ic|K zV}+U6_Uun8{uZC%pim2Cip%v(g#~D~%03iMhooJfj1rRb&N1pondtUg$s~EwM z87V~07|PKK_?kdBp1?7&3U8xd;$6=Nkgbg|&R~i(f?lX^#%T zRsw5BhG7x@cz~&Z{0wow{FPgu{j5tsA|FP4FMs(p#P|wo96%oR@xT7{uR%Gfs;dL? z&?`CvY#u&z%fBxKT0EP_6 z0hETiXfQwxtUU;%egK9xh}!7r2swj(shjyxc1tY{q(2*8i__KHh9aM-~7lUj{q)V_f@M_5wpDEh8uBcXgi2;k`p7%YDUJQM~@zZ z_+4GyEbuZ-BC-Kk+H7-((T6|up?o1ngA`AtQ)h4A{_0oX@UoY^oIK>lmMX}(G4M2S z@X^KbSbSh$3Feei!CRG6ro~}}AKrEwqakKYFS+DdJ9eB+#lnCr5I0Oz#OFTuIcmQ0 z%I9D8f)~bQk%YJ&suIb-{p_Xc#NCiUEW@C8zx&-|V`C`fAOmlyhY1D(x7T0)%19(S zlYh2?Q*PP>AQJ+`ysl+gcue2^*0UMOS}+&<^rb2FJNHDF|C=5}W4oA(Qp!S&Uz zemR>-C6jTiF)1+Y83bphQ2Y1v%*tT2b=17f|Lq_DW55oS{=eDTlM^yXcRpWWrN;Hw zzlvh8{w!P0quBzFWR~2jgrfLd(GfmrzgwW_;z@AN+?S{G;M~{2+qo%}olTtEesDkc zdu}Vi{k(ck&oDQI%GEUV$f?2$UxYut4y{kG?Ell0x!n(Bp`D^2KFLz20rBr8z--kgk)m)l z3y^wJ_-mt>A4P!~rj~+=cV=s#$ULbC%8*g=v}ti#SN?+%@IU6&r0j%BQ_as|^?4cR zJkEu9etmPY5&Jvk>EH1nZjkNgU{`Pt6!EX)^3fdXmaW@gI&h6I?caTX(Iu0H6J zu+ZtqA*HP~XX_AEqd=b(pcy#l{i?D-+Dw^wIpk4jd-CEzYF8KRa>~2eTuS)n5I}Ny zr^tk)2%jxnezqcYL!Q(7eQK675}=K4>21)QtXg6v6QeA*DH~L0?cp3~=5>w2Grc~w z~Ms1 zL6$VP*d;*oUco+_M-?FHOa*74R~V!uztSJoTnl7zGgB+o811^G9jRD2x6Qre4BGKY zmG``m@+TWt+(tL7W?6&1Ocs(d-J|KI;p^56I>|1m^>h^-60%BF?Ms09jju%|04A3? zEL~^LFcJa7bI%t(^O@&da8Wd#lrAd>PKP4svg#nv z&w?l@k_T{e8tA8p(cBE=l*|$;fv4Fh&K+}Lf*{`oTZGpG0D@tSv?oXk5JgFlDwL6C z1I;4$AXM_1zSF7}{i#u{USZly)#-E7w8AtY^JrAV$Fj6gOruf5^evlNIyRblZDdx=j|l!f8x-guwgv(tB02?Uz$uM zckkW@+*Uks_C*)p^tv|?kfqOXlyq{=6+k4jg>$hSAc<@WxwB7m$_2MGuNAA3P34qC zZY9X6+pH|Dv4o-Jx4fF6Cqkwfwk;r#V5Z1~f@enM2cq02hbCy(HO~d}x)Fg*3Zwq` zF{@gUQGEbyFain4M^zM{Wud&`8x|9)zG?9xUJCYw5`36RRkUGllXPn4W5u)bcA;zG zRC1Pc`TM^6gOQOjmb+WkGC{s_x!PztEdR(COXXTE5{uRsJ+U26)H~>n>KxSA7ItqtN8UAzA zYU-^9JfNP*FO078$ZHxCN=WRMd$ODQ+MQZ#?#``~JzbOlHODzJJYI7eb|^G4oo9N4 z_J;=(205`o=qmwG6%)l)9I1P%E-P$ zPne#yW7`GY@$N(<86Z)K2e)K|lvLX^Y9*~Qt@zha=mRS72O0QA;RG;)bg>LV71E_k zXro?t zrgNYsVwx=H8Xp^NJzN-C z*S+PLJD$y?li*!GU=g*cbM%4-Q`bvcwIn@2%M1U4S<#^K5%nS*Eh)Sr1tXz4sMueD zC>>T62Ym_(3h_u^^jeevSe$4mJnl5jrn@w4ZS3z_l}PpZdM(pk&KD*N<;i-Z;(LR- z{^-MxMmxWI&W;_~?w%zBOCzBWQUY+oRicEYqwP!X6qLcU;B(FuJo3$?66{Y0R3-el zo?B@;*g>1MD4Jjq!5Yc1h1HU|Y#{-AHzwgQYO9$3w zvdlAPeX}_=JvKPDH#aevNv3veIggzTq8Vr(Bf#z&L$h0+27elC;^zS(;AJI<1FpWUU%umXZQC{J~bF? zx`t;?wQ@^CVaE=Y4fCOT>CqF%AG`am>eP6uyKggV7Po9;Aq_NOkq`frh|Wbi@ScM9 zfFug-q)Yd?Ko8_A*7Ju)c0aJ|u5xv1syt;|;Y28viTAHteHL?&PQ~x*Seq*|#G9e?Jv9_$)zGm%)dZP(TvmI2q zQXmr}Om{KH;(E%2CpJAmkDwJ?%LCceO@LW&t%N|mQC$cKa4HP~GW>P~h?@GgSg2R? zF5JFlm6a+T%VTK9i-lHhx>c$Am@G}pB+_TcQVAA074iojew393tVd(Y_x$rNWG=MP zY(}FIvMHR3Hec{+qnu0u?t>r0I5u+V%eVj2SoxqIsf^{0q9JU<%2%g-Q?qxQAv5ZG zb}ZpL&8lUF8gA8SjrzrS*iNiode(_UM^>%d7)ymuOdST-&)9rPM}qnG4nwz_NRx;4 z#6Wm{3(r+h3A$@;E#jkTLRzzd+`<7Q3dp?Wu5D&Tpw*?I6*BReNfC+VqLAnvu`$R^ zkRrtwz7~~$XwzFYT@Jg=<(`>}*%Q@Tu3nxR8#9}Z$2^1S5ISV{0XO# zKQUCR*9VUsV_n8f>WHiorCtI3i@v73w-7|XNfK~w|2gAhOm>u$2cXjG6TT@gl2F)3`436jnB z1WdL&Hq)D#N1>!xUC~rN)*DBc3u??{Je>%O5X!7R_riTSqGSuI^;MvvbmGl>BBmYfqJjUAvUb zM2E)@*Xkue-L>ym>y~X@*S{rL^eFnw^# zc7#z_Evc4t1RPEo5sEg_Rga*Jq(~w8FH|F;1sUW)D7PpD79{{^=CTa^=&@tzRNTpx zood51%{ZYFSjhJfFqo*>a)+AbC-V80Z4azmv3BeBb1%GT)rwW&a0EsUJTpKLhjIq_ z(s2gZ0dgCSKp7+GNpWu@n%TtjD{@FaMPA~fxc#i zy<&LdEc;hmD z>5f9Xuouc~rsoU&E=~Z(VotN}x+CM0)u;A$rjkaZ9&h=DCIdw+Y*~>++_TL}HeT$` zuHA9&3(h-#^_sPrjxN&FLSNV#>(-(|V&8hyUv_+q`=HIom7Y;XMzJPfeJOdek!Gj=xbeD^+c( zVc1K(vAB+_km*j!j%hct^Q=qyvr7#>T=(j&rh~_$*6Rvb!lmME5$`dDHnMbiylY7)nbE9J zAeaI6X_0?z9trR-)=c$TINmq$lW;dYw^Xm9Em38DG3OoK7km6yz5AX_PfxxgWIk}P z@XMwV9q3P&y~;?bX0!%6(@WRKisKUvL*j^fD5S??y#oX2_X20wO&YN!89x=O<0QEC zSS#6YuhRAxN9qq(99N5myO;E*(p^mtHwOt85l7F+iZS_*SA;OgC`*)-ffE<8BMCj) zX;=|2Has$NqBeHI%a0n(n(aFgd|?|q7>a}=#6KX6Wm*u05uzF<1{OeCnBlzz@sHpy zLY!u;GI?}=Q!`q2*a}DD(J0HlncfeZCUg9{X$$87G3FTNWksCGpx7TJgzYaDDj|c4 z<0YM}WOP`8kDsRmKjb-K56@|;`Kw>L_uLsdx;IuS(g`COLnjnm>!UeqPcq5g-%_zO zQ7ms8=zi6fE$-0d@X(2Dt5tUzmK{c)gd<@@?P#+ybz#asXPa%azA5cIc5MH59&mK6 ztGCm^`@#E6CRXj-@w{uUN%syknvC{<7Y?N>q9z3GI6rbh1rn6p zh2g>a@Ui0fs8cFvwYt}+$+#EKO7~616NV8cDiRBaL0gDbJ}8S&{DrSEx|c3Ufkh?2 zio|->Y@%1hk`OHgB7=4prWV%qoIu!g(s&*8MBoN!`A;X5FE3KT%ccv``H~SXb_I5E z3>3O%l?!7(yDRy@@*qjiz!W20jy;B-3gwN@mPq2bB= z;lnAzDAsGKcp?>#xs4hxiP}b8tuoSBky^TQ(2!?)!B|HltT- zow4Yy+wU459DK!_-jwa@mvyTu)PPyD;V;W%NQ`?AqmaS}$l(-2Bih%fy4VaK&o{Mx zYuBb7ZlzGqPrAivt&;apQ}};1M&fm+TrSq@g<4I^7jbjxzG0bXU)ESS5_Ek-4MnwCoe+Y05! zw0rMxe|Bf;iCr<*A+GC!cMJbSBfJ4$7R$8WvZ7hGC1O<=ZLA1e17rD0xP}skobVbt zKF`4qwq14bV(f{0KBKLC@%h)Hpg-{sf0>&Yf9{K}`1LOy29l|%Y1Tzo8jU5r-MGv5 z-+lLsZoC;2owW3l+o~E~$_N`oT_A$4*>;S6hFf)dQ88^en=r6VpGAm?S+}aL9}cGy z%R3F|UMsnc2G#;z^AH78Fav3)fnYneno}p7*05r;Tl)orbFW1u06bEYh#`hwctNh& zo8VC;N%D*ullMXZkqV8I4j7lQlNd9F{z6AMEx&B(38xXh|L)cgZjJ7G*b-htZf!rE zFgh}|Qq{?qAOl5WnMAa!vwoyF5VFo+v*s*>yIRKmVD}3rrxod&c$6OHUSbhK2hvCW=vR&IRK?CM;xZOef>e!QYwj$uI!<9IIL zk%)Iqp3sK}bvqtiy2|M2s%vJG5t(6z{ALK{B7BC`MI;QLp}l4yI;hfGt;vR>ShlAQ zgVl)3xEx|@_$|-@u@L7dkD@5NaAGk5SlkA%)Re7_;>OOw`vL?wNeV$dB!d6NA}BfF zyY4qF7~IthdMj$U9V6q`cfRD_dpE9%9tqcNfmx5oy+o{8t@%?qt5Rz<)flNeo9swU zdZA&nGiJpw6~lu=iC83GqIO5d%BEdRy=FM9SwAs`o2^CcXeQ?O^)NT0 zS?2y}Enl}29bLsr*^0t*(UD_E%jHTj9zE!{4mKL;70YvD6FuqVaH)&~)2P>62hP>_ zaLj;%B$i6-g3L`#vv;NfTQ%JxlaAHeMSXp5>hwDbW5n}}zHYCpt2sJZthKz$ukO0} z%~K7pQYb_~p&bp!BJ_xu2Ut*j1jT{`<@}3n!0{xUg!~gOjD}2x4j4-%IzkO300Pd% z*zEnHDo7y|MmF&hpu8YnYNT1wH?tI&LA`i55CF`>Dda{7Q2%t+EliIi@0!!I>(|;h zzL-RO<1xl>;^ieH?8ciuG115siMd+kGI%gju}aAD?T}llCWwGGoAqh@zHX~lrS3?! zqfjmltXa2v&+bGt<~6H{WEa+bNsBYOM(||UYp0)X916`>TkNYg#M8FbhEtd3S^+aKK{O%tf^+TQ4zOrUP&ZgTa z!PizKT=8p|=ny=KD8QFNuvam$3}ldHIqwh12CJ7#g|U%53|B5Jd*Y$ceRqU#O2Uy= zDg~in^y*k%J2D1hh}h{7TklMHk#MQn2w9<6EL_i*yjp|ErKZKfeGO&Z-=C{i*{M2# z_N`S*x9fnJq_~oYc#O}S9Tzo-(YUVh1;~{z~o}rqQZu2EnQM@U0B({}=4clxw^E-pHQ+^jE0E`X~i>u5f-o5;TDnaR) z-?m;N?1OmPwuRHChFP-Nyp*5LjSaDJLo4J{^-4S&b1Ql?p76T+!g{N?Yp-6cit8N< zRYG>8D;w$TEL3WtZabAtwGJIh;I-D9dBbjWFB=jcwy}S7guW0r4*7b+G)lggXMKS0 zWmDa<*6ckE4 zim(J0w^n0hXG9~VVl{0v%6ELfkO(KPyvnr`HB(DRlKs)>WU*3m{7^K?=|D0xkTDxh zb_>x}0)Pc{E%bV`;YZkJqx95CeGwq}1)A5ND!;wPSkO?2{xS6_tcx)sVVT!L*f$6xemkfj^#^xV)2OE zVzOqcZeNUSKZ6>3F zAMu;<1ric>>l=ucDsHQptv8N*_Dkh*bJfi^ln8kha=r0HJZw&v3+UHSI?LQF_=Y{P zyPzM8DO3|{l0Y{iuJDG2ItAnN9u_44K4`I61TvZ4q78LX7@wM3_{#w6HX|yVvAB>2 zNyqUJr;Wi2e!946`N89MeY&VygUPOjrq%WOIy=5{-(hcj+DJz0mQe}Eq8(Xu9g7JP znUu|1n4w{NeA1{BJJzQ3(9a9Cr_|2(NHn_j{GCtjdUBGng#<5+RXv^OKKI#pGESjj zN1}|?fw+P#(fmra0(j@|JUd*ij*d?D_jI;OW$3gy9v^Phmw~5h)zNEKp=e|yzGeC$ zv95ZxEY>ZZ4fXd%!e)K4(Bn3Szy8&suCC?Rys+wUrpQRz3TMq)vknwfq11q9MOrdq zLvm~|CJP{ZLaPL?l}(^Fgg^q0i>jeT34rgwVNww$R-#eSt_&23eprltxUo^Yyh8Ix zBt^~d1?q`G7GX|IfZlQv@n~0Huc4N;FO5_*8D=`Zdj|TxX+kq)>e5!N)G> ziws0v^uUm`IWCEJJad2)>~c;e0kMMBR^eg z8HG|k+A&~L@9F77atAOlNfNNkjgx$#ko?Y#7v>^sAGF=EL?JZ=-U9~&Nd z_=);t$&QCRR;??_n6bEYA8ex>y9l zH5cxj-nFN2;CMFbB_m-$4wfm~4JevZ^$K|{lQxzwH;dJ~JWOM9bCd<;kOmqVY5b-Apy=$#mMbBXKv^DxC1sOO!%_{TD?0$;3qo0Cz7L zSfaMW3-Pd2YG{R9;R+7K>y=H$ylJ^a11+3BPr|^hW~opua2nOLz%74>zp?&4$?3T1~rFiz^^-}zRfPZs5_pi5G9Qzo5^&q;YM;#f|0ttK{UTOEyAg1xE3Vn9>ut6;;tXhO3= zK6oXHQfoxEp0z$|4nJ@YlDl%{suN@5ez6ed4-!ljV(_@G69KPiq2s!l^XgrhY;PjY zpNA-n=a!_ROq^$XJ0}{>c(YOTHT)cgq@0Dgci(=rE}j53>XJ(?!Y3Ke6-tn*TEi5% zQ`4O1Xs|w_o1==7=~5+f;6SR|h~upzZcSIK*LAvCt@|a114Uc)y2ePNyQe-~F!U0k zZQE&79^bp31I+La!n|?@ZK6Q*`dN@3-){13I)^Feb z;8S~1G98i7!RhItsj2RCn!&hMEG7HwT3xlIu5aJ zm5MmJvf12?YeYv9DZdO^+&Vh`=%6!RoQ!6wM-Ta}5~On*PB~Xj^z?5(_ZdmTj3c*e zZbb{TJ_`59R_A@|9A<&o}f#t~q9#S}e-EMmb;3_H{F!sy4l3Z+AGIByxbK3;W~0g0@__ z9LZ+4ocE04_;_V(44FN8bkIs9R;*o1P^eg`WczzLL4rep@f?Z`%txz(h#uxW8EI7= zrkGs#J&|Ns-oo)C)E+h8VvbZnVLY>D z^X6D*_x_1O;ju${!zi?@LPzh>bVqT;^61)S`0Ck?3`(%0D|LKu1iQ-l6XVBDjGY)N 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 G+ { if (codexStatus?.config) { const modelMatch = codexStatus.config.match(/^model\s*=\s*"([^"]+)"/m); if (modelMatch) setSelectedModel(modelMatch[1]); + + // Parse subagent settings + const subagentModelMatch = codexStatus.config.match(/\[agents\.subagent\]\s*\n\s*model\s*=\s*"([^"]+)"/m); + if (subagentModelMatch) setSubagentModel(subagentModelMatch[1]); } }, [codexStatus]); @@ -96,7 +102,12 @@ export default function CodexToolCard({ tool, isExpanded, onToggle, baseUrl, api const res = await fetch("/api/cli-tools/codex-settings", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ baseUrl: getEffectiveBaseUrl(), apiKey: keyToUse, model: selectedModel }), + body: JSON.stringify({ + baseUrl: getEffectiveBaseUrl(), + apiKey: keyToUse, + model: selectedModel, + subagentModel: subagentModel || selectedModel + }), }); const data = await res.json(); if (res.ok) { @@ -121,6 +132,7 @@ export default function CodexToolCard({ tool, isExpanded, onToggle, baseUrl, api if (res.ok) { setMessage({ type: "success", text: "Settings reset successfully!" }); setSelectedModel(""); + setSubagentModel(""); checkCodexStatus(); } else { setMessage({ type: "error", text: data.error || "Failed to reset settings" }); @@ -134,6 +146,10 @@ export default function CodexToolCard({ tool, isExpanded, onToggle, baseUrl, api const handleModelSelect = (model) => { setSelectedModel(model.value); + // Auto-set subagent model if not set + if (!subagentModel) { + setSubagentModel(model.value); + } setModalOpen(false); }; @@ -142,6 +158,8 @@ export default function CodexToolCard({ tool, isExpanded, onToggle, baseUrl, api ? selectedApiKey : (!cloudEnabled ? "sk_9router" : ""); + const effectiveSubagentModel = subagentModel || selectedModel; + const configContent = `# 9Router Configuration for Codex CLI model = "${selectedModel}" model_provider = "9router" @@ -150,6 +168,9 @@ model_provider = "9router" name = "9Router" base_url = "${getEffectiveBaseUrl()}" wire_api = "responses" + +[agents.subagent] +model = "${effectiveSubagentModel}" `; const authContent = JSON.stringify({ @@ -290,6 +311,35 @@ wire_api = "responses" {selectedModel && } + + {/* Subagent Model */} +
+ Subagent Model + arrow_forward + setSubagentModel(e.target.value)} + placeholder={selectedModel || "provider/model-id (defaults to main model)"} + className="flex-1 px-2 py-1.5 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50" + /> + + {subagentModel && ( + + )} +
{message && ( @@ -325,6 +375,16 @@ wire_api = "responses" title="Select Model for Codex" /> + setSubagentModalOpen(false)} + onSelect={(model) => { setSubagentModel(model.value); setSubagentModalOpen(false); }} + selectedModel={subagentModel} + activeProviders={activeProviders} + modelAliases={modelAliases} + title="Select Subagent Model for Codex" + /> + setShowManualConfigModal(false)} diff --git a/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js b/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js index 4ab16783..ca6ba00b 100644 --- a/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js +++ b/src/app/(dashboard)/dashboard/cli-tools/components/OpenCodeToolCard.js @@ -13,7 +13,9 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, const [showInstallGuide, setShowInstallGuide] = useState(false); const [selectedApiKey, setSelectedApiKey] = useState(""); const [selectedModel, setSelectedModel] = useState(""); + const [subagentModel, setSubagentModel] = useState(""); const [modalOpen, setModalOpen] = useState(false); + const [subagentModalOpen, setSubagentModalOpen] = useState(false); const [modelAliases, setModelAliases] = useState({}); const [showManualConfigModal, setShowManualConfigModal] = useState(false); const [customBaseUrl, setCustomBaseUrl] = useState(""); @@ -36,11 +38,16 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, if (isExpanded) fetchModelAliases(); }, [isExpanded]); - // Sync model from existing config + // Sync model and subagent model from existing config useEffect(() => { if (status?.config?.model?.startsWith("9router/")) { setSelectedModel(status.config.model.replace("9router/", "")); } + + // Parse subagent settings from agent.explorer if exists + if (status?.config?.agent?.explorer?.model?.startsWith("9router/")) { + setSubagentModel(status.config.agent.explorer.model.replace("9router/", "")); + } }, [status]); const fetchModelAliases = async () => { @@ -94,7 +101,12 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, const res = await fetch("/api/cli-tools/opencode-settings", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ baseUrl: getEffectiveBaseUrl(), apiKey: keyToUse, model: selectedModel }), + body: JSON.stringify({ + baseUrl: getEffectiveBaseUrl(), + apiKey: keyToUse, + model: selectedModel, + subagentModel: subagentModel || selectedModel + }), }); const data = await res.json(); if (res.ok) { @@ -119,6 +131,7 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, if (res.ok) { setMessage({ type: "success", text: "Settings reset successfully!" }); setSelectedModel(""); + setSubagentModel(""); checkStatus(); } else { setMessage({ type: "error", text: data.error || "Failed to reset settings" }); @@ -135,6 +148,8 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, ? selectedApiKey : (!cloudEnabled ? "sk_9router" : ""); + const effectiveSubagentModel = subagentModel || selectedModel; + return [{ filename: "~/.config/opencode/opencode.json", content: JSON.stringify({ @@ -142,10 +157,20 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, "9router": { npm: "@ai-sdk/openai-compatible", options: { baseURL: getEffectiveBaseUrl(), apiKey: keyToUse }, - models: { [selectedModel || "provider/model-id"]: { name: selectedModel || "provider/model-id" } }, + models: { + [selectedModel || "provider/model-id"]: { name: selectedModel || "provider/model-id" }, + [effectiveSubagentModel]: { name: effectiveSubagentModel } + }, }, }, model: `9router/${selectedModel || "provider/model-id"}`, + agent: { + explorer: { + description: "Fast explorer subagent for codebase exploration", + mode: "subagent", + model: `9router/${effectiveSubagentModel}` + } + } }, null, 2), }]; }; @@ -262,6 +287,35 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, {selectedModel && } + + {/* Subagent Model */} +
+ Subagent Model + arrow_forward + setSubagentModel(e.target.value)} + placeholder={selectedModel || "provider/model-id (defaults to main model)"} + className="flex-1 px-2 py-1.5 bg-surface rounded border border-border text-xs focus:outline-none focus:ring-1 focus:ring-primary/50" + /> + + {subagentModel && ( + + )} +
{message && ( @@ -290,13 +344,30 @@ export default function OpenCodeToolCard({ tool, isExpanded, onToggle, baseUrl, setModalOpen(false)} - onSelect={(model) => { setSelectedModel(model.value); setModalOpen(false); }} + onSelect={(model) => { + setSelectedModel(model.value); + // Auto-set subagent model if not set + if (!subagentModel) { + setSubagentModel(model.value); + } + setModalOpen(false); + }} selectedModel={selectedModel} activeProviders={activeProviders} modelAliases={modelAliases} title="Select Model for OpenCode" /> + setSubagentModalOpen(false)} + onSelect={(model) => { setSubagentModel(model.value); setSubagentModalOpen(false); }} + selectedModel={subagentModel} + activeProviders={activeProviders} + modelAliases={modelAliases} + title="Select Subagent Model for OpenCode" + /> + setShowManualConfigModal(false)} diff --git a/src/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js b/src/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js index 110a7666..0bf6e1b4 100644 --- a/src/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +++ b/src/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js @@ -2,19 +2,727 @@ import { useParams, notFound } from "next/navigation"; import Link from "next/link"; -import Image from "next/image"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { Card, Badge } from "@/shared/components"; -import { MEDIA_PROVIDER_KINDS, AI_PROVIDERS } from "@/shared/constants/providers"; +import ProviderIcon from "@/shared/components/ProviderIcon"; +import { MEDIA_PROVIDER_KINDS, AI_PROVIDERS, getProviderAlias } from "@/shared/constants/providers"; +import { getModelsByProviderId } from "@/shared/constants/models"; import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard"; import ConnectionsCard from "@/app/(dashboard)/dashboard/providers/components/ConnectionsCard"; import ModelsCard from "@/app/(dashboard)/dashboard/providers/components/ModelsCard"; +import { TTS_PROVIDER_CONFIG } from "@/shared/constants/ttsProviders"; +// Shared row layout — defined outside components to avoid re-mount on re-render +function Row({ label, children }) { + return ( +
+ {label} +
{children}
+
+ ); +} + +const DEFAULT_RESPONSE_EXAMPLE = `{ + "object": "list", + "data": [{ + "object": "embedding", + "index": 0, + "embedding": [0.002301, -0.019212, 0.004815, -0.031249, ...] + }], + "model": "...", + "usage": { "prompt_tokens": 9, "total_tokens": 9 } +}`; + +// EmbeddingExampleCard +function EmbeddingExampleCard({ providerId }) { + const providerAlias = getProviderAlias(providerId); + const embeddingModels = getModelsByProviderId(providerId).filter((m) => m.type === "embedding"); + + const [selectedModel, setSelectedModel] = useState(embeddingModels[0]?.id ?? ""); + const [input, setInput] = useState("The quick brown fox jumps over the lazy dog"); + const [apiKey, setApiKey] = useState(""); + const [useTunnel, setUseTunnel] = useState(false); + const [localEndpoint, setLocalEndpoint] = useState(""); + const [tunnelEndpoint, setTunnelEndpoint] = useState(""); + const [result, setResult] = useState(null); + const [running, setRunning] = useState(false); + const [error, setError] = useState(""); + const { copied: copiedCurl, copy: copyCurl } = useCopyToClipboard(); + const { copied: copiedRes, copy: copyRes } = useCopyToClipboard(); + + useEffect(() => { + setLocalEndpoint(window.location.origin); + fetch("/api/keys") + .then((r) => r.json()) + .then((d) => { setApiKey((d.keys || []).find((k) => k.isActive !== false)?.key || ""); }) + .catch(() => {}); + fetch("/api/tunnel/status") + .then((r) => r.json()) + .then((d) => { if (d.publicUrl) setTunnelEndpoint(d.publicUrl); }) + .catch(() => {}); + }, []); + + const endpoint = useTunnel ? tunnelEndpoint : localEndpoint; + const modelFull = selectedModel ? `${providerAlias}/${selectedModel}` : ""; + + const curlSnippet = `curl -X POST ${endpoint}/v1/embeddings \\ + -H "Content-Type: application/json" \\ + -H "Authorization: Bearer ${apiKey || "YOUR_KEY"}" \\ + -d '{"model": "${modelFull}", "input": "${input}"}'`; + + const handleRun = async () => { + if (!input.trim() || !modelFull) return; + setRunning(true); + setError(""); + setResult(null); + const start = Date.now(); + try { + const headers = { "Content-Type": "application/json" }; + if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`; + const res = await fetch("/api/v1/embeddings", { + method: "POST", + headers, + body: JSON.stringify({ model: modelFull, input: input.trim() }), + }); + const latencyMs = Date.now() - start; + const data = await res.json(); + if (!res.ok) { setError(data?.error?.message || data?.error || `HTTP ${res.status}`); return; } + setResult({ data, latencyMs }); + } catch (e) { + setError(e.message || "Network error"); + } finally { + setRunning(false); + } + }; + + // Compact embedding array: first 4 values + count + const formatResultJson = (data) => { + if (!data) return DEFAULT_RESPONSE_EXAMPLE; + const clone = JSON.parse(JSON.stringify(data)); + (clone.data || []).forEach((item) => { + if (Array.isArray(item.embedding) && item.embedding.length > 4) { + item.embedding = [...item.embedding.slice(0, 4).map((v) => parseFloat(v.toFixed(6))), `... (${item.embedding.length} dims)`]; + } + }); + return JSON.stringify(clone, null, 2); + }; + + const resultJson = result ? JSON.stringify(result.data, null, 2) : ""; + + return ( + +

Example

+ +
+ {/* Model */} + + + + + {/* Endpoint */} + +
+ useTunnel ? setTunnelEndpoint(e.target.value) : setLocalEndpoint(e.target.value)} + className="flex-1 px-3 py-1.5 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary font-mono" + placeholder="http://localhost:3000" + /> + {/* Tunnel toggle — only show if tunnel URL is available */} + {tunnelEndpoint && ( + + )} +
+
+ + {/* API Key */} + + setApiKey(e.target.value)} + placeholder="sk-..." + className="w-full px-3 py-1.5 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary font-mono" + /> + + + {/* Input */} + +
+ setInput(e.target.value)} + className="w-full px-3 py-1.5 pr-7 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary" + /> + {input && ( + + )} +
+
+ + {/* Curl + Run */} +
+
+ Request +
+ + +
+
+
{curlSnippet}
+
+ + {/* Error */} + {error &&

{error}

} + + {/* Response — default example or real result */} +
+
+ + Response {result && ⚡ {result.latencyMs}ms} + + {result && ( + + )} +
+
+            {formatResultJson(result?.data)}
+          
+
+
+
+ ); +} + +// ─── TTS Example Card ──────────────────────────────────────────────────────── +function TtsExampleCard({ providerId }) { + const providerAlias = getProviderAlias(providerId); + const config = TTS_PROVIDER_CONFIG[providerId] || TTS_PROVIDER_CONFIG["edge-tts"]; + + // Voice state + const [selectedVoice, setSelectedVoice] = useState(""); + const [selectedVoiceName, setSelectedVoiceName] = useState(""); + const [voiceId, setVoiceId] = useState(""); // editable voice id (elevenlabs) + // Voices shown below Voice row after language selected + const [countryVoices, setCountryVoices] = useState([]); + const [selectedLang, setSelectedLang] = useState(""); + const [selectedModel, setSelectedModel] = useState(() => { + if (config.hasModelSelector && config.modelKey) { + const models = getModelsByProviderId(config.modelKey); + return models?.[0]?.id || ""; + } + return ""; + }); + + // Form state + const [input, setInput] = useState("Hello, this is a text to speech test."); + const [apiKey, setApiKey] = useState(""); + const [useTunnel, setUseTunnel] = useState(false); + const [localEndpoint, setLocalEndpoint] = useState(""); + const [tunnelEndpoint, setTunnelEndpoint] = useState(""); + const [responseFormat, setResponseFormat] = useState("mp3"); // mp3 | json + const [audioUrl, setAudioUrl] = useState(""); + const [jsonResponse, setJsonResponse] = useState(null); // Store JSON response + const [running, setRunning] = useState(false); + const [error, setError] = useState(""); + const [latency, setLatency] = useState(null); + const { copied: copiedCurl, copy: copyCurl } = useCopyToClipboard(); + + // Country picker modal state + const [modalOpen, setModalOpen] = useState(false); + const [languages, setLanguages] = useState([]); + const [modalLoading, setModalLoading] = useState(false); + const [modalSearch, setModalSearch] = useState(""); + const [modalError, setModalError] = useState(""); + const [byLang, setByLang] = useState({}); + + useEffect(() => { + setLocalEndpoint(window.location.origin); + fetch("/api/keys") + .then((r) => r.json()) + .then((d) => { setApiKey((d.keys || []).find((k) => k.isActive !== false)?.key || ""); }) + .catch(() => {}); + fetch("/api/tunnel/status") + .then((r) => r.json()) + .then((d) => { if (d.publicUrl) setTunnelEndpoint(d.publicUrl); }) + .catch(() => {}); + + // Pre-select default voice based on provider config + if (config.voiceSource === "hardcoded") { + const voiceKey = config.voiceKey || providerId; + const voices = getModelsByProviderId(voiceKey).filter((m) => m.type === "tts"); + if (voices.length) { + if (config.hasLanguageDropdown) { + // Google TTS: just set voice + setSelectedVoice(voices[0].id); + setSelectedVoiceName(voices[0].name || voices[0].id); + } else { + // OpenAI: set voice chips + setCountryVoices(voices); + setSelectedVoice(voices[0].id); + setSelectedVoiceName(voices[0].name || voices[0].id); + } + } + } + // api-language (edge-tts, local-device, elevenlabs): NO default load, wait for user to pick language + }, [providerId]); + + // Open modal — load language list + const openModal = async () => { + setModalOpen(true); + setModalSearch(""); + setModalError(""); + if (languages.length) return; // already loaded + setModalLoading(true); + try { + // Use provider-specific apiEndpoint if available, else default to edge-tts voices API + const url = config.apiEndpoint + ? config.apiEndpoint + : `/api/media-providers/tts/voices?provider=${providerId === "local-device" ? "local-device" : "edge-tts"}`; + const r = await fetch(url); + const d = await r.json(); + if (d.error) { setModalError(d.error); return; } + setLanguages(d.languages || []); + setByLang(d.byLang || {}); + } catch (e) { + setModalError(e.message); + } finally { + setModalLoading(false); + } + }; + + // Click language → close modal → show voices below + const handlePickLanguage = (lang) => { + setModalOpen(false); + setSelectedLang(lang.code); + const voices = byLang[lang.code]?.voices || []; + setCountryVoices(voices); + // Auto-select first voice + if (voices.length) { + setSelectedVoice(voices[0].id); + setSelectedVoiceName(voices[0].name); + if (config.hasVoiceIdInput) setVoiceId(voices[0].id); + } + }; + + const filteredLanguages = modalSearch + ? languages.filter((c) => + c.name.toLowerCase().includes(modalSearch.toLowerCase()) || + c.code.toLowerCase().includes(modalSearch.toLowerCase()) + ) + : languages; + + const endpoint = useTunnel ? tunnelEndpoint : localEndpoint; + // For ElevenLabs: use voiceId (editable) instead of selectedVoice + const activeVoiceId = config.hasVoiceIdInput ? voiceId : selectedVoice; + const modelFull = config.hasModelSelector && activeVoiceId && selectedModel + ? `${providerAlias}/${selectedModel}/${activeVoiceId}` + : activeVoiceId ? `${providerAlias}/${activeVoiceId}` : ""; + + const curlSnippet = `curl -X POST ${endpoint}/v1/audio/speech${responseFormat === "json" ? "?response_format=json" : ""} \\ + -H "Content-Type: application/json" \\ + -H "Authorization: Bearer ${apiKey || "YOUR_KEY"}" \\ + -d '{"model": "${modelFull}", "input": "${input}"}' \\ + ${responseFormat === "json" ? "" : "--output speech.mp3"}`; + + const handleRun = async () => { + if (!input.trim() || !modelFull) return; + setRunning(true); + setError(""); + setAudioUrl(""); + setJsonResponse(null); + const start = Date.now(); + try { + const headers = { "Content-Type": "application/json" }; + if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`; + const url = `/api/v1/audio/speech${responseFormat === "json" ? "?response_format=json" : ""}`; + const res = await fetch(url, { + method: "POST", + headers, + body: JSON.stringify({ model: modelFull, input: input.trim() }), + }); + setLatency(Date.now() - start); + if (!res.ok) { + const d = await res.json().catch(() => ({})); + setError(d?.error?.message || d?.error || `HTTP ${res.status}`); + return; + } + + if (responseFormat === "json") { + const data = await res.json(); + setJsonResponse(data); // Store full JSON response + const audioBlob = await fetch(`data:audio/mp3;base64,${data.audio}`).then(r => r.blob()); + setAudioUrl(URL.createObjectURL(audioBlob)); + } else { + const blob = await res.blob(); + setAudioUrl(URL.createObjectURL(blob)); + } + } catch (e) { + setError(e.message || "Network error"); + } finally { + setRunning(false); + } + }; + + return ( + <> + +

Example

+ +
+ + + {/* Country Picker Modal */} + {modalOpen && ( +
setModalOpen(false)} + > +
e.stopPropagation()} + > + {/* Header */} +
+

Select Language

+ +
+ + {/* Search */} +
+ setModalSearch(e.target.value)} + placeholder="Search language..." + className="w-full px-3 py-1.5 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary" + /> +
+ + {/* Language list */} +
+ {modalError &&

{modalError}

} + {modalLoading ? ( +

Loading...

+ ) : ( +
+ {filteredLanguages.map((c) => ( + + ))} + {filteredLanguages.length === 0 && ( +

No languages found.

+ )} +
+ )} +
+
+
+ )} + + ); +} + +// MediaProviderDetailPage export default function MediaProviderDetailPage() { const { kind, id } = useParams(); - const { copied, copy } = useCopyToClipboard(); - const [headerImgError, setHeaderImgError] = useState(false); - const kindConfig = MEDIA_PROVIDER_KINDS.find((k) => k.id === kind); if (!kindConfig) return notFound(); @@ -24,8 +732,6 @@ export default function MediaProviderDetailPage() { const kinds = provider.serviceKinds ?? ["llm"]; if (!kinds.includes(kind)) return notFound(); - const endpointText = `${kindConfig.endpoint.method} ${kindConfig.endpoint.path}`; - return (
{/* Back */} @@ -40,21 +746,15 @@ export default function MediaProviderDetailPage() { {/* Header */}
-
- {headerImgError ? ( - - {provider.textIcon || provider.id.slice(0, 2).toUpperCase()} - - ) : ( - {provider.name} setHeaderImgError(true)} - /> - )} +
+

{provider.name}

@@ -69,25 +769,29 @@ export default function MediaProviderDetailPage() {
- {/* Endpoint block */} - -

{kindConfig.label} Endpoint

-
- - {kindConfig.endpoint.method} - - {kindConfig.endpoint.path} - -
-
+ {/* Connections */} + {provider.noAuth ? ( + +
+
+ lock_open +
+
+

No authentication required

+

This provider is ready to use.

+
+
+
+ ) : ( + + )} - {/* Connections — reuse shared component */} - + {/* Models - only for non-tts kinds */} + {kind !== "tts" && } - {/* Models — filtered by current kind */} - + {/* Example — per kind */} + {kind === "embedding" && } + {kind === "tts" && }
); } diff --git a/src/app/(dashboard)/dashboard/media-providers/[kind]/page.js b/src/app/(dashboard)/dashboard/media-providers/[kind]/page.js index 6d86b0af..ed7775a5 100644 --- a/src/app/(dashboard)/dashboard/media-providers/[kind]/page.js +++ b/src/app/(dashboard)/dashboard/media-providers/[kind]/page.js @@ -2,44 +2,91 @@ import { useParams, notFound } from "next/navigation"; import Link from "next/link"; -import { Card } from "@/shared/components"; +import { useEffect, useState } from "react"; +import { Card, Badge } from "@/shared/components"; import ProviderIcon from "@/shared/components/ProviderIcon"; import { MEDIA_PROVIDER_KINDS, AI_PROVIDERS, getProvidersByKind } from "@/shared/constants/providers"; -import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard"; + +function getEffectiveStatus(conn) { + const isCooldown = Object.entries(conn).some( + ([k, v]) => k.startsWith("modelLock_") && v && new Date(v).getTime() > Date.now() + ); + return conn.testStatus === "unavailable" && !isCooldown ? "active" : conn.testStatus; +} + +function MediaProviderCard({ provider, kind, connections }) { + const providerInfo = AI_PROVIDERS[provider.id]; + const isNoAuth = !!providerInfo?.noAuth; + + const providerConns = connections.filter((c) => c.provider === provider.id); + const connected = providerConns.filter((c) => { const s = getEffectiveStatus(c); return s === "active" || s === "success"; }).length; + const error = providerConns.filter((c) => { const s = getEffectiveStatus(c); return s === "error" || s === "expired" || s === "unavailable"; }).length; + const total = providerConns.length; + const allDisabled = total > 0 && providerConns.every((c) => c.isActive === false); + + const renderStatus = () => { + if (isNoAuth) return Ready; + if (allDisabled) return Disabled; + if (total === 0) return No connections; + return ( + <> + {connected > 0 && {connected} Connected} + {error > 0 && {error} Error} + {connected === 0 && error === 0 && {total} Added} + + ); + }; + + return ( + + +
+
7 ? provider.color : (provider.color ?? "#888") + "15"}` }} + > + +
+
+

{provider.name}

+
+ {renderStatus()} +
+
+
+
+ + ); +} export default function MediaProviderKindPage() { const { kind } = useParams(); - const { copied, copy } = useCopyToClipboard(); + const [connections, setConnections] = useState([]); const kindConfig = MEDIA_PROVIDER_KINDS.find((k) => k.id === kind); if (!kindConfig) return notFound(); const providers = getProvidersByKind(kind); - const endpointText = `${kindConfig.endpoint.method} ${kindConfig.endpoint.path}`; + + useEffect(() => { + fetch("/api/providers", { cache: "no-store" }) + .then((r) => r.json()) + .then((d) => setConnections(d.connections || [])) + .catch(() => {}); + }, []); return (
- {/* Endpoint block */} - -

Endpoint

-
- - {kindConfig.endpoint.method} - - {kindConfig.endpoint.path} - -
-
- - {/* Provider list */} {providers.length === 0 ? (
No providers support {kindConfig.label} yet. @@ -47,29 +94,12 @@ export default function MediaProviderKindPage() { ) : (
{providers.map((provider) => ( - - -
-
7 ? provider.color : (provider.color ?? "#888") + "15"}` }} - > - -
-
-

{provider.name}

-

{(provider.serviceKinds ?? ["llm"]).join(", ")}

-
-
-
- + ))}
)} diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.js b/src/app/(dashboard)/dashboard/providers/[id]/page.js index 80618edf..b5f1374b 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/page.js +++ b/src/app/(dashboard)/dashboard/providers/[id]/page.js @@ -549,10 +549,11 @@ export default function ProviderDetailPage() { ); } // Combine hardcoded models with Kilo free models (deduplicated) + // Exclude non-llm models (embedding, tts, etc.) — they have dedicated pages under media-providers const displayModels = [ ...models, ...kiloFreeModels.filter((fm) => !models.some((m) => m.id === fm.id)), - ]; + ].filter((m) => !m.type || m.type === "llm"); // Custom models added by user (stored as aliases: modelId → providerAlias/modelId) const customModels = Object.entries(modelAliases) .filter(([alias, fullModel]) => { @@ -1579,7 +1580,7 @@ function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMov }; return ( -
+
{/* Priority arrows */}
diff --git a/src/app/(dashboard)/dashboard/providers/components/ConnectionsCard.js b/src/app/(dashboard)/dashboard/providers/components/ConnectionsCard.js index a80f19e3..30a69fb0 100644 --- a/src/app/(dashboard)/dashboard/providers/components/ConnectionsCard.js +++ b/src/app/(dashboard)/dashboard/providers/components/ConnectionsCard.js @@ -104,7 +104,7 @@ function ConnectionRow({ connection, proxyPools, isOAuth, isFirst, isLast, onMov }; return ( -
+
*/} - {mediaOpen && ( -
- {MEDIA_PROVIDER_KINDS.map((kind) => ( - - {kind.icon} - {kind.label} - - ))} -
- )} - - {/* System section */}

System

+ + {/* Media Providers accordion */} + + {mediaOpen && ( +
+ {MEDIA_PROVIDER_KINDS.filter((k) => VISIBLE_MEDIA_KINDS.includes(k.id)).map((kind) => ( + + {kind.icon} + {kind.label} + + ))} +
+ )} + {systemItems.map((item) => ( { export function getProvidersByKind(kind) { return Object.values(AI_PROVIDERS).filter((p) => { const kinds = p.serviceKinds ?? ["llm"]; - return kinds.includes(kind); + if (!kinds.includes(kind)) return false; + if (p.hidden) return false; // globally hidden + if (p.hiddenKinds?.includes(kind)) return false; // hidden for specific kind + return true; }); } diff --git a/src/shared/constants/ttsProviders.js b/src/shared/constants/ttsProviders.js new file mode 100644 index 00000000..0117febb --- /dev/null +++ b/src/shared/constants/ttsProviders.js @@ -0,0 +1,41 @@ +/** + * TTS Provider Configuration + * Centralized config for TTS provider UI behavior + */ +export const TTS_PROVIDER_CONFIG = { + "google-tts": { + hasLanguageDropdown: true, + hasModelSelector: false, + hasBrowseButton: false, + voiceSource: "hardcoded", // from providerModels + }, + "openai": { + hasLanguageDropdown: false, + hasModelSelector: true, + hasBrowseButton: false, + voiceSource: "hardcoded", // from providerModels + modelKey: "openai-tts-models", + voiceKey: "openai-tts-voices", + }, + "elevenlabs": { + hasLanguageDropdown: false, + hasModelSelector: true, + hasBrowseButton: true, + hasVoiceIdInput: true, // allow manual voice id entry + voiceSource: "api-language", // grouped by language from backend + modelKey: "elevenlabs-tts-models", + apiEndpoint: "/api/media-providers/tts/elevenlabs/voices", + }, + "edge-tts": { + hasLanguageDropdown: false, + hasModelSelector: false, + hasBrowseButton: true, + voiceSource: "api-language", // from API with language picker + }, + "local-device": { + hasLanguageDropdown: false, + hasModelSelector: false, + hasBrowseButton: true, + voiceSource: "api-language", // from API with language picker + }, +}; diff --git a/src/sse/handlers/tts.js b/src/sse/handlers/tts.js new file mode 100644 index 00000000..18ac5bee --- /dev/null +++ b/src/sse/handlers/tts.js @@ -0,0 +1,85 @@ +import { + extractApiKey, isValidApiKey, + getProviderCredentials, markAccountUnavailable, +} from "../services/auth.js"; +import { getSettings } from "@/lib/localDb"; +import { getModelInfo } from "../services/model.js"; +import { handleTtsCore } from "open-sse/handlers/ttsCore.js"; +import { errorResponse, unavailableResponse } from "open-sse/utils/error.js"; +import { HTTP_STATUS } from "open-sse/config/runtimeConfig.js"; +import * as log from "../utils/logger.js"; + +// Providers that require stored credentials (not noAuth) +const CREDENTIALED_PROVIDERS = new Set(["openai", "elevenlabs"]); + +export async function handleTts(request) { + let body; + try { + body = await request.json(); + } catch { + return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid JSON body"); + } + + const url = new URL(request.url); + const modelStr = body.model; + const responseFormat = url.searchParams.get("response_format") || "mp3"; // mp3 (default) | json + log.request("POST", `${url.pathname} | ${modelStr} | format=${responseFormat}`); + + const settings = await getSettings(); + if (settings.requireApiKey) { + const apiKey = extractApiKey(request); + if (!apiKey) return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Missing API key"); + const valid = await isValidApiKey(apiKey); + if (!valid) return errorResponse(HTTP_STATUS.UNAUTHORIZED, "Invalid API key"); + } + + if (!modelStr) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing model"); + if (!body.input) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Missing required field: input"); + + const modelInfo = await getModelInfo(modelStr); + if (!modelInfo.provider) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid model format"); + + const { provider, model } = modelInfo; + log.info("ROUTING", `Provider: ${provider}, Voice: ${model}`); + + // noAuth providers — no credential needed + if (!CREDENTIALED_PROVIDERS.has(provider)) { + const result = await handleTtsCore({ provider, model, input: body.input, responseFormat }); + if (result.success) return result.response; + return errorResponse(result.status || HTTP_STATUS.BAD_GATEWAY, result.error || "TTS failed"); + } + + // Credentialed providers — fallback loop (same pattern as embeddings) + const excludeConnectionIds = new Set(); + let lastError = null; + let lastStatus = null; + + while (true) { + const credentials = await getProviderCredentials(provider, excludeConnectionIds, model); + + if (!credentials || credentials.allRateLimited) { + if (credentials?.allRateLimited) { + const msg = lastError || credentials.lastError || "Unavailable"; + const status = lastStatus || Number(credentials.lastErrorCode) || HTTP_STATUS.SERVICE_UNAVAILABLE; + return unavailableResponse(status, `[${provider}/${model}] ${msg}`, credentials.retryAfter, credentials.retryAfterHuman); + } + if (excludeConnectionIds.size === 0) return errorResponse(HTTP_STATUS.BAD_REQUEST, `No credentials for provider: ${provider}`); + return errorResponse(lastStatus || HTTP_STATUS.SERVICE_UNAVAILABLE, lastError || "All accounts unavailable"); + } + + log.info("AUTH", `\x1b[32mUsing ${provider} account: ${credentials.connectionName}\x1b[0m`); + + const result = await handleTtsCore({ provider, model, input: body.input, credentials, responseFormat }); + + if (result.success) return result.response; + + const { shouldFallback } = await markAccountUnavailable(credentials.connectionId, result.status, result.error, provider, model); + if (shouldFallback) { + excludeConnectionIds.add(credentials.connectionId); + lastError = result.error; + lastStatus = result.status; + continue; + } + return result.response || errorResponse(result.status, result.error); + } +}
+ {/* Endpoint + API Key as read-only text */} + +
+ + {endpoint}/v1/audio/speech + + {tunnelEndpoint && ( + + )} +
+
+ + + {apiKey ? `${apiKey.slice(0, 8)}${"•".repeat(Math.min(20, apiKey.length - 8))}` : No key configured} + + + + {/* Model selector (OpenAI, ElevenLabs) */} + {config.hasModelSelector && config.modelKey && ( + + + + )} + + {/* Language row + Browse button (edge-tts, local-device, elevenlabs) */} + {config.hasBrowseButton && ( + +
+ + +
+
+ )} + + {/* Voice chips — shown after language picked (edge-tts, local-device) or always (OpenAI/ElevenLabs) */} + {countryVoices.length > 0 && ( + +
+ {countryVoices.map((v) => ( + + ))} +
+
+ )} + + {/* Voice ID input (ElevenLabs) — manual entry or auto-fill from chip */} + {config.hasVoiceIdInput && ( + +
+
+ { + setVoiceId(e.target.value); + setSelectedVoice(e.target.value); + }} + placeholder="e.g. CwhRBWXzGAHq8TQ4Fs17" + className="w-full px-3 py-1.5 pr-7 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary font-mono" + /> + {voiceId && ( + + )} +
+
+
+ )} + + {/* Google TTS: Language dropdown */} + {config.hasLanguageDropdown && ( + + + + )} + + {/* Input */} + +
+ setInput(e.target.value)} + className="w-full px-3 py-1.5 pr-7 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary" + /> + {input && ( + + )} +
+
+ + {/* Output Format */} + + + + + {/* Curl + Run */} +
+
+ Request +
+ + +
+
+
{curlSnippet}
+
+ + {error &&

{error}

} + + {/* Audio player */} + {audioUrl ? ( +
+ +
+ ) : ( +

Audio will appear here after running.

+ )} +