LibreChat/api/server/routes/settings.js
Marco Beretta d5cccb5f18
feat: add favorites for marketplace tools, MCP servers, and skills
Reintroduce the favorite star from the old skill picker, generalized to
every marketplace item kind except per-agent actions. Cards in the Tool
Library and Skills dialogs get a hover-revealed star (always visible once
favorited), and the existing Favorites views in both dialogs now filter to
starred items.

Favorites persist in a dedicated ToolFavorite collection, one document per
(user, itemType, itemId) with a unique compound index, exposed through
atomic per-item PUT/DELETE endpoints under /api/user/settings/favorites/
tools. Per-item writes are idempotent and race-free across tabs/devices
(the unique index backstops concurrent toggles), reads are a single
index-backed query capped at 100 favorites per user, and the client keeps
React Query as the source of truth with optimistic updates. Handlers live
in @librechat/api with a thin route wrapper; methods follow the
data-schemas factory pattern with tenant isolation.

The favorites filter now matches on compound kind:id keys instead of bare
ids, closing a cross-kind collision where a tool and a skill sharing an id
would both match. The skill-favorites data-service stubs and the reserved
TUserFavorite.skillId field are replaced by the new tool-favorites service.
2026-07-03 01:12:31 +02:00

34 lines
1.2 KiB
JavaScript

const express = require('express');
const { createToolFavoritesHandlers } = require('@librechat/api');
const {
updateFavoritesController,
getFavoritesController,
} = require('~/server/controllers/FavoritesController');
const {
getSkillStatesController,
updateSkillStatesController,
} = require('~/server/controllers/SkillStatesController');
const { requireJwtAuth } = require('~/server/middleware');
const { getToolFavorites, addToolFavorite, removeToolFavorite } = require('~/models');
const router = express.Router();
const toolFavorites = createToolFavoritesHandlers({
getToolFavorites,
addToolFavorite,
removeToolFavorite,
});
router.get('/favorites/tools', requireJwtAuth, toolFavorites.listToolFavorites);
router.put('/favorites/tools/:itemType/:itemId', requireJwtAuth, toolFavorites.addToolFavorite);
router.delete(
'/favorites/tools/:itemType/:itemId',
requireJwtAuth,
toolFavorites.removeToolFavorite,
);
router.get('/favorites', requireJwtAuth, getFavoritesController);
router.post('/favorites', requireJwtAuth, updateFavoritesController);
router.get('/skills/active', requireJwtAuth, getSkillStatesController);
router.post('/skills/active', requireJwtAuth, updateSkillStatesController);
module.exports = router;