refactor(open-sse): B1 consolidate media endpoint URLs into registry
- image/embed/tts/search base URLs derive from media.*Config.baseUrl / searchViaChat.endpoint (single source); handlers read PROVIDER_MEDIA. - ~18 hardcoded endpoints moved: bfl/fal/stability/runway/hf/gemini/ cloudflare/recraft/sdwebui/comfyui/nanobanana image, voyage embed, gemini/openrouter tts, chatSearch endpoints. - Byte-identical: PROVIDERS 62 + alias 90 baselines, image buildUrl outputs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,6 @@ import { PROVIDER_MEDIA } from "../../providers/index.js";
|
|||||||
|
|
||||||
// media-only providers without a registry file keep URL here; rest derive from registry media.embeddingConfig.baseUrl
|
// media-only providers without a registry file keep URL here; rest derive from registry media.embeddingConfig.baseUrl
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
"voyage-ai": "https://api.voyageai.com/v1/embeddings",
|
|
||||||
"jina-ai": "https://api.jina.ai/v1/embeddings",
|
"jina-ai": "https://api.jina.ai/v1/embeddings",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Black Forest Labs (FLUX) — async submit + polling_url
|
// Black Forest Labs (FLUX) — async submit + polling_url
|
||||||
import { sleep, nowSec, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
import { sleep, nowSec, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://api.bfl.ai/v1";
|
const BASE_URL = PROVIDER_MEDIA["black-forest-labs"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async: true,
|
async: true,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { nowSec, urlToBase64 } from "./_base.js";
|
import { nowSec, urlToBase64 } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://api.cloudflare.com/client/v4/accounts";
|
const BASE_URL = PROVIDER_MEDIA["cloudflare-ai"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
const MULTIPART_MODELS = new Set([
|
const MULTIPART_MODELS = new Set([
|
||||||
"@cf/black-forest-labs/flux-2-dev",
|
"@cf/black-forest-labs/flux-2-dev",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
// ComfyUI — local, noAuth (placeholder; full graph workflow not implemented)
|
// ComfyUI — local, noAuth (placeholder; full graph workflow not implemented)
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
|
const BASE_URL = PROVIDER_MEDIA["comfyui"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
noAuth: true,
|
noAuth: true,
|
||||||
buildUrl: () => "http://localhost:8188",
|
buildUrl: () => BASE_URL,
|
||||||
buildHeaders: () => ({ "Content-Type": "application/json" }),
|
buildHeaders: () => ({ "Content-Type": "application/json" }),
|
||||||
buildBody: (_model, body) => ({ prompt: body.prompt }),
|
buildBody: (_model, body) => ({ prompt: body.prompt }),
|
||||||
normalize: (responseBody) => responseBody,
|
normalize: (responseBody) => responseBody,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Fal.ai — async submit + queue polling
|
// Fal.ai — async submit + queue polling
|
||||||
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://queue.fal.run";
|
const BASE_URL = PROVIDER_MEDIA["fal-ai"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async: true,
|
async: true,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Google Gemini adapter (Nano Banana models)
|
// Google Gemini adapter (Nano Banana models)
|
||||||
import { nowSec } from "./_base.js";
|
import { nowSec } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models";
|
const BASE_URL = PROVIDER_MEDIA["gemini"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
buildUrl: (model, creds) => {
|
buildUrl: (model, creds) => {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// HuggingFace Inference API — returns binary image
|
// HuggingFace Inference API — returns binary image
|
||||||
import { nowSec } from "./_base.js";
|
import { nowSec } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://api-inference.huggingface.co/models";
|
const BASE_URL = PROVIDER_MEDIA["huggingface"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
buildUrl: (model) => `${BASE_URL}/${model}`,
|
buildUrl: (model) => `${BASE_URL}/${model}`,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// NanoBanana API — async submit + poll record-info
|
// NanoBanana API — async submit + poll record-info
|
||||||
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const SUBMIT_URL = "https://api.nanobananaapi.ai/api/v1/nanobanana/generate";
|
const IMG_CFG = PROVIDER_MEDIA["nanobanana"]?.imageConfig || {};
|
||||||
const POLL_BASE = "https://api.nanobananaapi.ai/api/v1/nanobanana/record-info";
|
const SUBMIT_URL = IMG_CFG.baseUrl;
|
||||||
|
const POLL_BASE = IMG_CFG.pollUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async: true,
|
async: true,
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
// OpenAI-compatible adapter (used by openai, minimax, openrouter, recraft)
|
// OpenAI-compatible adapter (used by openai, minimax, openrouter, recraft)
|
||||||
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
// media-only providers without a registry file keep their URL here; rest derive from registry media.imageConfig.baseUrl
|
|
||||||
const ENDPOINTS = {
|
|
||||||
recraft: "https://external.api.recraft.ai/v1/images/generations",
|
|
||||||
};
|
|
||||||
|
|
||||||
const imageCfg = (id) => PROVIDER_MEDIA[id]?.imageConfig || {};
|
const imageCfg = (id) => PROVIDER_MEDIA[id]?.imageConfig || {};
|
||||||
const imageUrl = (id) => imageCfg(id).baseUrl || ENDPOINTS[id];
|
const imageUrl = (id) => imageCfg(id).baseUrl;
|
||||||
|
|
||||||
export default function createOpenAIAdapter(providerId) {
|
export default function createOpenAIAdapter(providerId) {
|
||||||
const cfg = imageCfg(providerId);
|
const cfg = imageCfg(providerId);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Runway ML — async submit + /tasks/{id} polling
|
// Runway ML — async submit + /tasks/{id} polling
|
||||||
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
import { sleep, nowSec, sizeToAspectRatio, POLL_INTERVAL_MS, POLL_TIMEOUT_MS } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://api.dev.runwayml.com/v1";
|
const BASE_URL = PROVIDER_MEDIA["runwayml"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async: true,
|
async: true,
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
// SD WebUI (AUTOMATIC1111) — local, noAuth
|
// SD WebUI (AUTOMATIC1111) — local, noAuth
|
||||||
import { nowSec } from "./_base.js";
|
import { nowSec } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
|
const BASE_URL = PROVIDER_MEDIA["sdwebui"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
noAuth: true,
|
noAuth: true,
|
||||||
buildUrl: () => "http://localhost:7860/sdapi/v1/txt2img",
|
buildUrl: () => BASE_URL,
|
||||||
buildHeaders: () => ({ "Content-Type": "application/json" }),
|
buildHeaders: () => ({ "Content-Type": "application/json" }),
|
||||||
buildBody: (_model, body) => {
|
buildBody: (_model, body) => {
|
||||||
const { prompt, n = 1, size = "1024x1024" } = body;
|
const { prompt, n = 1, size = "1024x1024" } = body;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// Stability AI v2 — sync, returns { image: "<b64>" }
|
// Stability AI v2 — sync, returns { image: "<b64>" }
|
||||||
import { nowSec, sizeToAspectRatio } from "./_base.js";
|
import { nowSec, sizeToAspectRatio } from "./_base.js";
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const BASE_URL = "https://api.stability.ai/v2beta/stable-image/generate";
|
const BASE_URL = PROVIDER_MEDIA["stability-ai"]?.imageConfig?.baseUrl;
|
||||||
|
|
||||||
// Map model id → endpoint segment
|
// Map model id → endpoint segment
|
||||||
function modelToEndpoint(model) {
|
function modelToEndpoint(model) {
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
// Default search model derives from registry searchViaChat (single source)
|
// Default search model + endpoint derive from registry searchViaChat (single source)
|
||||||
const searchModel = (id) => PROVIDER_MEDIA[id]?.searchViaChat?.defaultModel;
|
const searchModel = (id) => PROVIDER_MEDIA[id]?.searchViaChat?.defaultModel;
|
||||||
|
const searchEndpoint = (id, model) =>
|
||||||
|
(PROVIDER_MEDIA[id]?.searchViaChat?.endpoint || "").replace("{model}", model || "");
|
||||||
|
|
||||||
const REQUEST_TIMEOUT_MS = 15000;
|
const REQUEST_TIMEOUT_MS = 15000;
|
||||||
const DEFAULT_MAX_RESULTS = 10;
|
const DEFAULT_MAX_RESULTS = 10;
|
||||||
@@ -47,8 +49,7 @@ function normalizeCitation(c) {
|
|||||||
*/
|
*/
|
||||||
const CHAT_SEARCH_CONFIG = {
|
const CHAT_SEARCH_CONFIG = {
|
||||||
gemini: {
|
gemini: {
|
||||||
endpoint: (model) =>
|
endpoint: (model) => searchEndpoint("gemini", model),
|
||||||
`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent`,
|
|
||||||
buildBody: (query) => ({
|
buildBody: (query) => ({
|
||||||
contents: [{ role: "user", parts: [{ text: query }] }],
|
contents: [{ role: "user", parts: [{ text: query }] }],
|
||||||
tools: [{ google_search: {} }]
|
tools: [{ google_search: {} }]
|
||||||
@@ -73,7 +74,7 @@ const CHAT_SEARCH_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
openai: {
|
openai: {
|
||||||
endpoint: () => "https://api.openai.com/v1/chat/completions",
|
endpoint: () => searchEndpoint("openai"),
|
||||||
buildBody: (query, model) => {
|
buildBody: (query, model) => {
|
||||||
const body = {
|
const body = {
|
||||||
model,
|
model,
|
||||||
@@ -107,7 +108,7 @@ const CHAT_SEARCH_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
xai: {
|
xai: {
|
||||||
endpoint: () => "https://api.x.ai/v1/responses",
|
endpoint: () => searchEndpoint("xai"),
|
||||||
buildBody: (query, model) => ({
|
buildBody: (query, model) => ({
|
||||||
model,
|
model,
|
||||||
input: [{ role: "user", content: query }],
|
input: [{ role: "user", content: query }],
|
||||||
@@ -146,7 +147,7 @@ const CHAT_SEARCH_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
kimi: {
|
kimi: {
|
||||||
endpoint: () => "https://api.moonshot.cn/v1/chat/completions",
|
endpoint: () => searchEndpoint("kimi"),
|
||||||
buildBody: (query, model) => ({
|
buildBody: (query, model) => ({
|
||||||
model,
|
model,
|
||||||
messages: [{ role: "user", content: query }],
|
messages: [{ role: "user", content: query }],
|
||||||
@@ -195,7 +196,7 @@ const CHAT_SEARCH_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
minimax: {
|
minimax: {
|
||||||
endpoint: () => "https://api.minimaxi.com/v1/text/chatcompletion_v2",
|
endpoint: () => searchEndpoint("minimax"),
|
||||||
buildBody: (query, model) => ({
|
buildBody: (query, model) => ({
|
||||||
model,
|
model,
|
||||||
messages: [{ role: "user", content: query }],
|
messages: [{ role: "user", content: query }],
|
||||||
@@ -253,7 +254,7 @@ const CHAT_SEARCH_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
perplexity: {
|
perplexity: {
|
||||||
endpoint: () => "https://api.perplexity.ai/chat/completions",
|
endpoint: () => searchEndpoint("perplexity"),
|
||||||
buildBody: (query, model) => ({
|
buildBody: (query, model) => ({
|
||||||
model,
|
model,
|
||||||
messages: [{ role: "user", content: query }]
|
messages: [{ role: "user", content: query }]
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
import { Buffer } from "node:buffer";
|
import { Buffer } from "node:buffer";
|
||||||
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
const KNOWN_MODELS = (PROVIDER_MEDIA["gemini"]?.ttsConfig?.models || []).map((m) => m.id);
|
const TTS_CFG = PROVIDER_MEDIA["gemini"]?.ttsConfig || {};
|
||||||
|
const TTS_BASE = TTS_CFG.baseUrl;
|
||||||
|
const KNOWN_MODELS = (TTS_CFG.models || []).map((m) => m.id);
|
||||||
const DEFAULT_MODEL = KNOWN_MODELS[0];
|
const DEFAULT_MODEL = KNOWN_MODELS[0];
|
||||||
const DEFAULT_VOICE = "Kore";
|
const DEFAULT_VOICE = "Kore";
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ export default {
|
|||||||
async synthesize(text, model, credentials, _responseFormat, opts = {}) {
|
async synthesize(text, model, credentials, _responseFormat, opts = {}) {
|
||||||
if (!credentials?.apiKey) throw new Error("No Gemini API key configured");
|
if (!credentials?.apiKey) throw new Error("No Gemini API key configured");
|
||||||
const { modelId, voiceId } = parseGeminiModelVoice(model);
|
const { modelId, voiceId } = parseGeminiModelVoice(model);
|
||||||
const url = `https://generativelanguage.googleapis.com/v1beta/models/${modelId}:generateContent?key=${credentials.apiKey}`;
|
const url = `${TTS_BASE}/${modelId}:generateContent?key=${credentials.apiKey}`;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
// OpenRouter TTS — via chat completions + audio modality (SSE stream)
|
// OpenRouter TTS — via chat completions + audio modality (SSE stream)
|
||||||
|
import { PROVIDER_MEDIA } from "../../providers/index.js";
|
||||||
|
|
||||||
|
const TTS_CFG = PROVIDER_MEDIA["openrouter"]?.ttsConfig || {};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async synthesize(text, model, credentials) {
|
async synthesize(text, model, credentials) {
|
||||||
if (!credentials?.apiKey) throw new Error("No OpenRouter API key configured");
|
if (!credentials?.apiKey) throw new Error("No OpenRouter API key configured");
|
||||||
|
|
||||||
// model format: "tts-model/voice" e.g. "openai/gpt-4o-mini-tts/alloy"
|
// model format: "tts-model/voice" e.g. "openai/gpt-4o-mini-tts/alloy"
|
||||||
let ttsModel = "openai/gpt-4o-mini-tts";
|
let ttsModel = TTS_CFG.defaultModel;
|
||||||
let voice = "alloy";
|
let voice = "alloy";
|
||||||
if (model && model.includes("/")) {
|
if (model && model.includes("/")) {
|
||||||
const lastSlash = model.lastIndexOf("/");
|
const lastSlash = model.lastIndexOf("/");
|
||||||
@@ -20,13 +24,12 @@ export default {
|
|||||||
voice = model;
|
voice = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
const res = await fetch(TTS_CFG.baseUrl, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Authorization": `Bearer ${credentials.apiKey}`,
|
"Authorization": `Bearer ${credentials.apiKey}`,
|
||||||
"HTTP-Referer": "https://endpoint-proxy.local",
|
...(TTS_CFG.headers || {}),
|
||||||
"X-Title": "Endpoint Proxy",
|
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: ttsModel,
|
model: ttsModel,
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export default {
|
|||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
aliases: ["bfl"],
|
aliases: ["bfl"],
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "https://api.bfl.ai/v1" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "flux-pro-1.1",
|
"id": "flux-pro-1.1",
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export default {
|
|||||||
},
|
},
|
||||||
media: {
|
media: {
|
||||||
serviceKinds: ["llm", "image"],
|
serviceKinds: ["llm", "image"],
|
||||||
hasProviderSpecificData: true
|
hasProviderSpecificData: true,
|
||||||
|
imageConfig: { baseUrl: "https://api.cloudflare.com/client/v4/accounts" }
|
||||||
},
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export default {
|
|||||||
},
|
},
|
||||||
category: "apikey",
|
category: "apikey",
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "http://localhost:8188" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "flux-dev",
|
"id": "flux-dev",
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export default {
|
|||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
aliases: ["fal"],
|
aliases: ["fal"],
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "https://queue.fal.run" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "fal-ai/flux/schnell",
|
"id": "fal-ai/flux/schnell",
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ export default {
|
|||||||
ttsConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", format: "gemini-tts", models: [{ id: "gemini-2.5-flash-preview-tts", name: "Gemini 2.5 Flash TTS" }, { id: "gemini-2.5-pro-preview-tts", name: "Gemini 2.5 Pro TTS" }] },
|
ttsConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", format: "gemini-tts", models: [{ id: "gemini-2.5-flash-preview-tts", name: "Gemini 2.5 Flash TTS" }, { id: "gemini-2.5-pro-preview-tts", name: "Gemini 2.5 Pro TTS" }] },
|
||||||
sttConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", format: "gemini-stt", models: [{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro (Best)" }, { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" }, { id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite (Cheapest)" }, { id: "gemini-2.0-flash", name: "Gemini 2.0 Flash" }] },
|
sttConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", format: "gemini-stt", models: [{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro (Best)" }, { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" }, { id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite (Cheapest)" }, { id: "gemini-2.0-flash", name: "Gemini 2.0 Flash" }] },
|
||||||
embeddingConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", models: [{ id: "text-embedding-004", name: "Text Embedding 004", dimensions: 768 }, { id: "embedding-001", name: "Embedding 001", dimensions: 768 }] },
|
embeddingConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models", authType: "apikey", authHeader: "key", models: [{ id: "text-embedding-004", name: "Text Embedding 004", dimensions: 768 }, { id: "embedding-001", name: "Embedding 001", dimensions: 768 }] },
|
||||||
searchViaChat: { defaultModel: "gemini-2.5-flash", pricingUrl: "https://ai.google.dev/pricing", freeTier: "Free tier: 15 RPM, 1M tokens/day on gemini-2.5-flash via AI Studio." }
|
searchViaChat: { defaultModel: "gemini-2.5-flash", endpoint: "https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent", pricingUrl: "https://ai.google.dev/pricing", freeTier: "Free tier: 15 RPM, 1M tokens/day on gemini-2.5-flash via AI Studio." },
|
||||||
|
imageConfig: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/models" }
|
||||||
},
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ export default {
|
|||||||
hiddenKinds: ["tts"],
|
hiddenKinds: ["tts"],
|
||||||
aliases: ["hf"],
|
aliases: ["hf"],
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
imageConfig: { baseUrl: "https://api-inference.huggingface.co/models" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "black-forest-labs/FLUX.1-schnell",
|
"id": "black-forest-labs/FLUX.1-schnell",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default {
|
|||||||
},
|
},
|
||||||
media: {
|
media: {
|
||||||
serviceKinds: ["llm", "webSearch"],
|
serviceKinds: ["llm", "webSearch"],
|
||||||
searchViaChat: { defaultModel: "kimi-k2.5", pricingUrl: "https://platform.moonshot.ai/docs/pricing/chat" }
|
searchViaChat: { defaultModel: "kimi-k2.5", endpoint: "https://api.moonshot.cn/v1/chat/completions", pricingUrl: "https://platform.moonshot.ai/docs/pricing/chat" }
|
||||||
},
|
},
|
||||||
models: [
|
models: [
|
||||||
{ id: "kimi-k2.6", name: "Kimi K2.6" },
|
{ id: "kimi-k2.6", name: "Kimi K2.6" },
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default {
|
|||||||
media: {
|
media: {
|
||||||
serviceKinds: ["llm", "image", "imageToText", "webSearch", "tts"],
|
serviceKinds: ["llm", "image", "imageToText", "webSearch", "tts"],
|
||||||
ttsConfig: { baseUrl: "https://api.minimax.io/v1/t2a_v2", authType: "apikey", authHeader: "bearer", format: "minimax-tts", models: [{ id: "speech-2.8-hd", name: "Speech 2.8 HD" }, { id: "speech-2.8-turbo", name: "Speech 2.8 Turbo" }, { id: "speech-2.6-hd", name: "Speech 2.6 HD" }, { id: "speech-2.6-turbo", name: "Speech 2.6 Turbo" }, { id: "speech-02-hd", name: "Speech 02 HD" }, { id: "speech-02-turbo", name: "Speech 02 Turbo" }, { id: "speech-01-hd", name: "Speech 01 HD" }, { id: "speech-01-turbo", name: "Speech 01 Turbo" }] },
|
ttsConfig: { baseUrl: "https://api.minimax.io/v1/t2a_v2", authType: "apikey", authHeader: "bearer", format: "minimax-tts", models: [{ id: "speech-2.8-hd", name: "Speech 2.8 HD" }, { id: "speech-2.8-turbo", name: "Speech 2.8 Turbo" }, { id: "speech-2.6-hd", name: "Speech 2.6 HD" }, { id: "speech-2.6-turbo", name: "Speech 2.6 Turbo" }, { id: "speech-02-hd", name: "Speech 02 HD" }, { id: "speech-02-turbo", name: "Speech 02 Turbo" }, { id: "speech-01-hd", name: "Speech 01 HD" }, { id: "speech-01-turbo", name: "Speech 01 Turbo" }] },
|
||||||
searchViaChat: { defaultModel: "MiniMax-M2.7", pricingUrl: "https://www.minimaxi.com/document/price" },
|
searchViaChat: { defaultModel: "MiniMax-M2.7", endpoint: "https://api.minimaxi.com/v1/text/chatcompletion_v2", pricingUrl: "https://www.minimaxi.com/document/price" },
|
||||||
imageConfig: { baseUrl: "https://api.minimaxi.com/v1/images/generations" }
|
imageConfig: { baseUrl: "https://api.minimaxi.com/v1/images/generations" }
|
||||||
},
|
},
|
||||||
models: [
|
models: [
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ export default {
|
|||||||
"baseUrl": "https://api.nanobananaapi.ai/v1/chat/completions",
|
"baseUrl": "https://api.nanobananaapi.ai/v1/chat/completions",
|
||||||
"validateUrl": "https://api.nanobananaapi.ai/v1/models"
|
"validateUrl": "https://api.nanobananaapi.ai/v1/models"
|
||||||
},
|
},
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["llm", "image"],
|
||||||
|
imageConfig: { baseUrl: "https://api.nanobananaapi.ai/api/v1/nanobanana/generate", pollUrl: "https://api.nanobananaapi.ai/api/v1/nanobanana/record-info" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "nanobanana-flash",
|
"id": "nanobanana-flash",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export default {
|
|||||||
embeddingConfig: { baseUrl: "https://openrouter.ai/api/v1/embeddings", authType: "apikey", authHeader: "bearer", headers: { "HTTP-Referer": "https://endpoint-proxy.local", "X-Title": "Endpoint Proxy" }, models: [{ id: "openai/text-embedding-3-small", name: "Text Embedding 3 Small (OpenRouter)", dimensions: 1536 }, { id: "openai/text-embedding-3-large", name: "Text Embedding 3 Large (OpenRouter)", dimensions: 3072 }, { id: "openai/text-embedding-ada-002", name: "Text Embedding Ada 002 (OpenRouter)", dimensions: 1536 }] },
|
embeddingConfig: { baseUrl: "https://openrouter.ai/api/v1/embeddings", authType: "apikey", authHeader: "bearer", headers: { "HTTP-Referer": "https://endpoint-proxy.local", "X-Title": "Endpoint Proxy" }, models: [{ id: "openai/text-embedding-3-small", name: "Text Embedding 3 Small (OpenRouter)", dimensions: 1536 }, { id: "openai/text-embedding-3-large", name: "Text Embedding 3 Large (OpenRouter)", dimensions: 3072 }, { id: "openai/text-embedding-ada-002", name: "Text Embedding Ada 002 (OpenRouter)", dimensions: 1536 }] },
|
||||||
modelsFetcher: { url: "https://openrouter.ai/api/v1/models", type: "openrouter-free" },
|
modelsFetcher: { url: "https://openrouter.ai/api/v1/models", type: "openrouter-free" },
|
||||||
imageConfig: { baseUrl: "https://openrouter.ai/api/v1/images/generations", headers: { "HTTP-Referer": "https://endpoint-proxy.local", "X-Title": "Endpoint Proxy" } },
|
imageConfig: { baseUrl: "https://openrouter.ai/api/v1/images/generations", headers: { "HTTP-Referer": "https://endpoint-proxy.local", "X-Title": "Endpoint Proxy" } },
|
||||||
|
ttsConfig: { baseUrl: "https://openrouter.ai/api/v1/chat/completions", defaultModel: "openai/gpt-4o-mini-tts", headers: { "HTTP-Referer": "https://endpoint-proxy.local", "X-Title": "Endpoint Proxy" } },
|
||||||
passthroughModels: true
|
passthroughModels: true
|
||||||
},
|
},
|
||||||
"models": [
|
"models": [
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default {
|
|||||||
},
|
},
|
||||||
media: {
|
media: {
|
||||||
serviceKinds: ["llm", "webSearch"],
|
serviceKinds: ["llm", "webSearch"],
|
||||||
searchViaChat: { defaultModel: "sonar", pricingUrl: "https://docs.perplexity.ai/guides/pricing" }
|
searchViaChat: { defaultModel: "sonar", endpoint: "https://api.perplexity.ai/chat/completions", pricingUrl: "https://docs.perplexity.ai/guides/pricing" }
|
||||||
},
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ export default {
|
|||||||
category: "apikey",
|
category: "apikey",
|
||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "https://external.api.recraft.ai/v1/images/generations" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "recraftv3",
|
"id": "recraftv3",
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export default {
|
|||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
aliases: ["runway"],
|
aliases: ["runway"],
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "https://api.dev.runwayml.com/v1" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "gen4_image",
|
"id": "gen4_image",
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export default {
|
|||||||
},
|
},
|
||||||
category: "apikey",
|
category: "apikey",
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "http://localhost:7860/sdapi/v1/txt2img" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "stable-diffusion-v1-5",
|
"id": "stable-diffusion-v1-5",
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export default {
|
|||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
aliases: ["stability"],
|
aliases: ["stability"],
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["image"],
|
||||||
|
imageConfig: { baseUrl: "https://api.stability.ai/v2beta/stable-image/generate" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "stable-image-ultra",
|
"id": "stable-image-ultra",
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ export default {
|
|||||||
uiAlias: "voyage",
|
uiAlias: "voyage",
|
||||||
authType: "apikey",
|
authType: "apikey",
|
||||||
"transport": null,
|
"transport": null,
|
||||||
|
media: {
|
||||||
|
serviceKinds: ["embedding"],
|
||||||
|
embeddingConfig: { baseUrl: "https://api.voyageai.com/v1/embeddings" }
|
||||||
|
},
|
||||||
"models": [
|
"models": [
|
||||||
{
|
{
|
||||||
"id": "voyage-3-large",
|
"id": "voyage-3-large",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
},
|
},
|
||||||
media: {
|
media: {
|
||||||
serviceKinds: ["llm", "imageToText", "webSearch", "image"],
|
serviceKinds: ["llm", "imageToText", "webSearch", "image"],
|
||||||
searchViaChat: { defaultModel: "grok-4.20-reasoning", pricingUrl: "https://x.ai/api#pricing" },
|
searchViaChat: { defaultModel: "grok-4.20-reasoning", endpoint: "https://api.x.ai/v1/responses", pricingUrl: "https://x.ai/api#pricing" },
|
||||||
imageConfig: { baseUrl: "https://api.x.ai/v1/images/generations", bodyFields: ["model", "prompt", "n", "response_format"] },
|
imageConfig: { baseUrl: "https://api.x.ai/v1/images/generations", bodyFields: ["model", "prompt", "n", "response_format"] },
|
||||||
authModes: ["oauth", "apikey"],
|
authModes: ["oauth", "apikey"],
|
||||||
hasOAuth: true
|
hasOAuth: true
|
||||||
|
|||||||
Reference in New Issue
Block a user