@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
95 lines (94 loc) • 4.66 kB
JavaScript
/**
* Music Module — Music Generation Integration for NeuroLink
*
* Provides music-generation capability across providers (Beatoven,
* ElevenLabs Music, Lyria, Replicate-hosted MusicGen / Riffusion).
*
* Use `MusicProcessor.generate(provider, options)` to dispatch to the
* registered handler for `provider`.
*
* Importing this module does NOT register any handlers as a side effect.
* Call `registerDefaultMusicHandlers()` explicitly (or go through
* `ProviderRegistry.registerAllProviders()`, which every documented
* `NeuroLink` entry point already calls) to register every shipped music
* handler whose backing API key is present in `process.env`. Registration
* is idempotent and silently skipped if a provider is already registered or
* its constructor throws (e.g. missing optional native dependency).
*
* @module music
*/
import { MEDIA_HANDLER_CATALOG } from "../factories/mediaHandlerCatalog.js";
import { logger } from "../utils/logger.js";
import { MusicProcessor } from "../utils/musicProcessor.js";
export { MUSIC_ERROR_CODES, MusicError, MusicProcessor, } from "../utils/musicProcessor.js";
// ============================================================================
// HANDLER CLASSES
// ============================================================================
export { BeatovenMusic, BeatovenMusic as BeatovenMusicHandler, } from "./providers/BeatovenMusic.js";
export { ElevenLabsMusic, ElevenLabsMusic as ElevenLabsMusicHandler, } from "./providers/ElevenLabsMusic.js";
export { LyriaMusic, LyriaMusic as LyriaMusicHandler, } from "./providers/LyriaMusic.js";
export { ReplicateMusic, ReplicateMusic as ReplicateMusicHandler, } from "./providers/ReplicateMusic.js";
// ============================================================================
// AUTO-REGISTRATION
// ============================================================================
import { BeatovenMusic } from "./providers/BeatovenMusic.js";
import { ElevenLabsMusic } from "./providers/ElevenLabsMusic.js";
import { LyriaMusic } from "./providers/LyriaMusic.js";
import { ReplicateMusic } from "./providers/ReplicateMusic.js";
// Provider names + aliases are the Task-8 catalog's job — only the factory
// (which needs the imported handler class) stays local to this module.
const MUSIC_HANDLER_FACTORIES = {
beatoven: () => new BeatovenMusic(),
"elevenlabs-music": () => new ElevenLabsMusic(),
lyria: () => new LyriaMusic(),
replicate: () => new ReplicateMusic(),
};
const MUSIC_HANDLER_CANDIDATES = MEDIA_HANDLER_CATALOG.filter((entry) => entry.kind === "music").map((entry) => {
const factory = MUSIC_HANDLER_FACTORIES[entry.name];
if (!factory) {
throw new Error(`[music] no handler factory for catalog entry "${entry.name}"`);
}
return { name: entry.name, aliases: entry.aliases, factory };
});
/**
* Register every shipped music handler whose backing credentials are
* present in the environment. Safe to call multiple times — existing
* registrations are preserved.
*/
export function registerDefaultMusicHandlers() {
for (const { name, aliases, factory } of MUSIC_HANDLER_CANDIDATES) {
// Compute missingName / missingAliases separately so a pre-registered
// primary doesn't block alias backfill — keeps "musicgen" reachable
// when only "replicate" was wired up via another path (and likewise
// "elevenlabs-sound" vs "elevenlabs-music").
const missingName = !MusicProcessor.supports(name);
const missingAliases = (aliases ?? []).filter((alias) => !MusicProcessor.supports(alias));
if (!missingName && missingAliases.length === 0) {
continue;
}
try {
// Reuse the already-registered primary's handler for alias backfill
// when one exists — wiring an alias to a factory-fresh instance
// would silently diverge from the canonical primary's config.
let handler;
if (!missingName) {
handler = MusicProcessor.getHandler(name);
}
if (!handler) {
handler = factory();
if (!handler.isConfigured()) {
continue;
}
}
if (missingName) {
MusicProcessor.registerHandler(name, handler);
}
for (const alias of missingAliases) {
MusicProcessor.registerHandler(alias, handler);
}
}
catch (err) {
logger.debug(`[music] ${name} auto-registration skipped: ${err instanceof Error ? err.message : String(err)}`);
}
}
}