YuKumo
Changelog

v1.6.0 — Resilience & Plugins

Queue persistence, WS heartbeats, SponsorBlock + live lyrics integration, player protections, destroy reasons, and link policy.

Released 2026-08-04 · npm install yukumo@1.6.0

The reliability release: dead-connection detection, runaway-player guards, and queues that survive redeploys — plus first-class SponsorBlock and live lyrics.

Added

Queue Persistence

queueOptions.persist auto-saves every queue to the configured StorageAdapter (microtask-coalesced — a 500-track playlist add is one write) and restores it on createPlayer(). Persisted queues are kept on shutdown (DisconnectAllNodes) and deleted on normal destroys. New Player.enableQueuePersistence() / Player.restoreQueue() and a Queue.onChanged mutation hook.

WebSocket Heartbeat

Ping/pong dead-connection detection per node (enableHeartbeat, heartbeatIntervalMs = 30000, heartbeatTimeoutMs = 10000). Half-open sockets are terminated and reconnect automatically; new ws.isAlive getter.

SponsorBlock Plugin Integration

player.setSponsorBlock(categories) / getSponsorBlock() / deleteSponsorBlock() plus segmentsLoaded, segmentSkipped, chaptersLoaded, chapterStarted events — server-side auto-skip via the Lavalink SponsorBlock plugin.

Live Lyrics (LavaLyrics)

player.getCurrentLyrics(), subscribeLyrics(), unsubscribeLyrics() plus lyricsFound, lyricsNotFound, lyricsLine events — timestamped lyric lines streamed as the track plays.

Player & Manager API

  • Play options — play() / playTrack() accept { position, endTime, noReplace, paused, volume }.
  • Player protections (defaults via ManagerOptions.playerDefaults) — maxErrorsPerTime sliding-window error-rate destroy ({ threshold: 35000, maxAmount: 3 }), minAutoPlayMs autoplay error-spam guard (10000ms), queueEmptyDestroyMs destroy-after-queue-end timer.
  • Destroy reasons — DestroyReasons enum; destroy(reason) everywhere; playerDestroy now emits (guildId, reason).
  • Link policy — linksAllowed, linksWhitelist, linksBlacklist (substring or RegExp) gate URL queries in search().
  • Custom HTTP headers — ManagerOptions.httpHeaders (global) and NodeConfig.httpHeaders (per node) on REST + WS handshake.
  • Player — toJSON() full snapshot, ping getter { ws, lavalink }, moveNode(nodeId?) least-loaded auto-pick.
  • Queue — sortBy("duration" | "title" | "author" | comparator, order), removeTrack(track | tracks | predicate).
  • Filters — setAudioOutput("mono" | "stereo" | "left" | "right") channel-mix presets (AudioOutputs export).
  • Custom Player class — ManagerOptions.playerClass.
  • Utils — parseLavalinkConnUrl("lavalink://name:pass@host:port").

Fixed

  • Player leak: direct player.destroy() (auto-disconnect, channel delete) now unregisters from PlayerManager and decrements node.playerCount.
  • Race: track-end handling (natural end / stuck / skip) is serialized — no more double queue-advances.
  • position interpolates between playerUpdate frames (clamped to track length) instead of being up to ~5s stale; seek() clamps to [0, length].
  • resume() on an idle player no longer fakes "playing"; pause() / resume() are idempotent.
  • setVolume() is remembered while the node session is down and applied on next play.
  • skip() with nothing playing no longer crashes the autoplay path.
  • Empty-VC and queue-empty timers are unref()ed — they no longer keep the process alive.

On this page