mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-02 06:10:18 +01:00
💻 feat: Deeper MCP UI integration in the Chat UI (#9669)
* 💻 feat: deeper MCP UI integration in the chat UI using plugins --------- Co-authored-by: Samuel Path <samuel.path@shopify.com> Co-authored-by: Pierre-Luc Godin <pierreluc.godin@shopify.com> * 💻 refactor: Migrate MCP UI resources from index-based to ID-based referencing - Replace index-based resource markers with stable resource IDs - Update plugin to parse \ui{resourceId} format instead of \ui0 - Refactor components to use useMessagesOperations instead of useSubmitMessage - Add ShareMessagesProvider for UI resources in share view - Add useConversationUIResources hook for cross-turn resource lookups - Update parsers to generate resource IDs from content hashes - Update all tests to use resource IDs instead of indices - Add sandbox permissions for iframe popups - Remove deprecated MCP tool context instructions --------- Co-authored-by: Pierre-Luc Godin <pierreluc.godin@shopify.com>
This commit is contained in:
parent
4a0fbb07bc
commit
304bba853c
27 changed files with 1545 additions and 122 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { atom } from 'recoil';
|
||||
import { atom, selectorFamily } from 'recoil';
|
||||
import { TAttachment } from 'librechat-data-provider';
|
||||
import { atomWithLocalStorage } from './utils';
|
||||
import { BadgeItem } from '~/common';
|
||||
|
|
@ -10,6 +10,43 @@ const messageAttachmentsMap = atom<Record<string, TAttachment[] | undefined>>({
|
|||
default: {},
|
||||
});
|
||||
|
||||
/**
|
||||
* Selector to get attachments for a specific conversation.
|
||||
*/
|
||||
const conversationAttachmentsSelector = selectorFamily<
|
||||
Record<string, TAttachment[]>,
|
||||
string | undefined
|
||||
>({
|
||||
key: 'conversationAttachments',
|
||||
get:
|
||||
(conversationId) =>
|
||||
({ get }) => {
|
||||
if (!conversationId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const attachmentsMap = get(messageAttachmentsMap);
|
||||
const result: Record<string, TAttachment[]> = {};
|
||||
|
||||
// Filter to only include attachments for this conversation
|
||||
Object.entries(attachmentsMap).forEach(([messageId, attachments]) => {
|
||||
if (!attachments) {
|
||||
return;
|
||||
}
|
||||
|
||||
const relevantAttachments = attachments.filter(
|
||||
(attachment) => attachment.conversationId === conversationId,
|
||||
);
|
||||
|
||||
if (relevantAttachments.length > 0) {
|
||||
result[messageId] = relevantAttachments;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
const queriesEnabled = atom<boolean>({
|
||||
key: 'queriesEnabled',
|
||||
default: true,
|
||||
|
|
@ -30,6 +67,7 @@ const chatBadges = atomWithLocalStorage<Pick<BadgeItem, 'id'>[]>('chatBadges', [
|
|||
export default {
|
||||
hideBannerHint,
|
||||
messageAttachmentsMap,
|
||||
conversationAttachmentsSelector,
|
||||
queriesEnabled,
|
||||
isEditingBadges,
|
||||
chatBadges,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue