api9nin / src /shared /constants /providers.js
github-actions[bot]
deploy from github actions 2026-06-18
c8ae75d
Raw
History Blame Contribute Delete
6.63 kB
// Provider definitions
import REGISTRY from "open-sse/providers/registry/index.js";
import { RISK_NOTICE } from "@/shared/constants/providersDisplay";
const MEDIA_ENTRY_KEYS = [
"serviceKinds", "ttsConfig", "sttConfig", "embeddingConfig",
"imageConfig", "imageToTextConfig", "videoConfig", "musicConfig",
"searchViaChat", "searchConfig", "fetchConfig",
"modelsFetcher", "mediaPriority", "hiddenKinds",
];
// Build provider UI object from registry entry
function buildProviderEntry(r) {
const mediaFields = {};
if (r.media) Object.assign(mediaFields, r.media);
for (const k of MEDIA_ENTRY_KEYS) {
if (r[k] !== undefined) mediaFields[k] = r[k];
}
const display = { ...(r.display || {}) };
if (display.deprecationNotice === "RISK_NOTICE") display.deprecationNotice = RISK_NOTICE;
return {
...display,
id: r.id,
alias: r.uiAlias || r.alias,
...(r.hidden ? { hidden: true } : {}),
...mediaFields,
...(r.priority !== undefined ? { priority: r.priority } : {}),
...(r.hasFree ? { hasFree: true } : {}),
...(r.thinkingConfig ? { thinkingConfig: r.thinkingConfig } : {}),
...(r.regions ? { regions: r.regions, defaultRegion: r.defaultRegion } : {}),
...(r.hasProviderSpecificData ? { hasProviderSpecificData: true } : {}),
...(r.noAuth ? { noAuth: true } : {}),
...(r.passthroughModels ? { passthroughModels: true } : {}),
...(r.hasOAuth ? { hasOAuth: true } : {}),
...(r.authModes ? { authModes: r.authModes } : {}),
...(r.authType ? { authType: r.authType } : {}),
...(r.authHint ? { authHint: r.authHint } : {}),
};
}
const byCategory = (cat) => Object.fromEntries(
REGISTRY.filter(r => r.category === cat).map(r => [r.id, buildProviderEntry(r)])
);
export const FREE_PROVIDERS = byCategory("free");
export const FREE_TIER_PROVIDERS = byCategory("freeTier");
// Thinking config definitions
// options: list of selectable modes ("auto" = no override from server)
// defaultMode: fallback when user hasn't configured
// extended: claude-style thinking (thinking.type + budget_tokens) — used by most providers
// effort: openai-style reasoning_effort — only openai + codex
export const THINKING_CONFIG = {
extended: {
options: ["auto", "on", "off"],
defaultMode: "auto",
defaultBudgetTokens: 10000
},
effort: {
options: ["auto", "none", "low", "medium", "high"],
defaultMode: "auto"
}
};
export const OAUTH_PROVIDERS = byCategory("oauth");
export const APIKEY_PROVIDERS = byCategory("apikey");
// Web Cookie Providers (use browser session cookie instead of API key)
export const WEB_COOKIE_PROVIDERS = byCategory("webCookie");
// Media provider kinds — each kind maps to a route and endpoint config
export const MEDIA_PROVIDER_KINDS = [
{ id: "embedding", label: "Embedding", icon: "data_array", endpoint: { method: "POST", path: "/v1/embeddings" } },
{ id: "image", label: "Text to Image", icon: "brush", endpoint: { method: "POST", path: "/v1/images/generations" } },
{ id: "imageToText", label: "Image to Text", icon: "image_search", endpoint: { method: "POST", path: "/v1/images/understanding" } },
{ id: "tts", label: "Text To Speech", icon: "record_voice_over", endpoint: { method: "POST", path: "/v1/audio/speech" } },
{ id: "stt", label: "Speech To Text", icon: "mic", endpoint: { method: "POST", path: "/v1/audio/transcriptions" } },
{ id: "webSearch", label: "Web Search", icon: "travel_explore", endpoint: { method: "POST", path: "/v1/search" } },
{ id: "webFetch", label: "Web Fetch", icon: "language", endpoint: { method: "POST", path: "/v1/web/fetch" } },
{ id: "video", label: "Video", icon: "movie", endpoint: { method: "POST", path: "/v1/video/generations" } },
{ id: "music", label: "Music", icon: "music_note", endpoint: { method: "POST", path: "/v1/audio/music" } },
];
export const OPENAI_COMPATIBLE_PREFIX = "openai-compatible-";
export const ANTHROPIC_COMPATIBLE_PREFIX = "anthropic-compatible-";
export const CUSTOM_EMBEDDING_PREFIX = "custom-embedding-";
export function isOpenAICompatibleProvider(providerId) {
return typeof providerId === "string" && providerId.startsWith(OPENAI_COMPATIBLE_PREFIX);
}
export function isAnthropicCompatibleProvider(providerId) {
return typeof providerId === "string" && providerId.startsWith(ANTHROPIC_COMPATIBLE_PREFIX);
}
export function isCustomEmbeddingProvider(providerId) {
return typeof providerId === "string" && providerId.startsWith(CUSTOM_EMBEDDING_PREFIX);
}
// All providers (combined)
export const AI_PROVIDERS = { ...FREE_PROVIDERS, ...FREE_TIER_PROVIDERS, ...OAUTH_PROVIDERS, ...APIKEY_PROVIDERS, ...WEB_COOKIE_PROVIDERS };
// Auth methods
export const AUTH_METHODS = {
oauth: { id: "oauth" },
apikey: { id: "apikey" },
cookie: { id: "cookie" },
};
// Helper: Get provider by alias
export function getProviderByAlias(alias) {
for (const provider of Object.values(AI_PROVIDERS)) {
if (provider.alias === alias || provider.id === alias) {
return provider;
}
}
return null;
}
// Helper: Get provider ID from alias
export function resolveProviderId(aliasOrId) {
const provider = getProviderByAlias(aliasOrId);
return provider?.id || aliasOrId;
}
// Helper: Get alias from provider ID
export function getProviderAlias(providerId) {
const provider = AI_PROVIDERS[providerId];
return provider?.alias || providerId;
}
// Alias to ID mapping (for quick lookup)
export const ALIAS_TO_ID = Object.values(AI_PROVIDERS).reduce((acc, p) => {
acc[p.alias] = p.id;
return acc;
}, {});
// ID to Alias mapping
export const ID_TO_ALIAS = Object.values(AI_PROVIDERS).reduce((acc, p) => {
acc[p.id] = p.alias;
return acc;
}, {});
// Helper: Get providers by service kind (e.g. "tts", "embedding", "image")
// Providers without serviceKinds default to ["llm"]
export function getProvidersByKind(kind) {
return Object.values(AI_PROVIDERS)
.filter((p) => {
const kinds = p.serviceKinds ?? ["llm"];
if (!kinds.includes(kind)) return false;
if (p.hidden) return false;
if (p.hiddenKinds?.includes(kind)) return false;
return true;
})
.sort((a, b) => (a.priority ?? a.mediaPriority ?? 999) - (b.priority ?? b.mediaPriority ?? 999));
}
// Derive từ registry features flags
export const USAGE_SUPPORTED_PROVIDERS = REGISTRY
.filter(r => r.features?.usage)
.map(r => r.id);
export const USAGE_APIKEY_PROVIDERS = REGISTRY
.filter(r => r.features?.usageApikey)
.map(r => r.id);