mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-18 01:10:14 +01:00
💻 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
This commit is contained in:
parent
9ae81a85a5
commit
48a26e3504
20 changed files with 643 additions and 606 deletions
|
|
@ -1,7 +1,12 @@
|
|||
import crypto from 'node:crypto';
|
||||
import { Tools } from 'librechat-data-provider';
|
||||
import type { UIResource } from 'librechat-data-provider';
|
||||
import type * as t from './types';
|
||||
|
||||
function generateResourceId(text: string): string {
|
||||
return crypto.createHash('sha256').update(text).digest('hex').substring(0, 10);
|
||||
}
|
||||
|
||||
const RECOGNIZED_PROVIDERS = new Set([
|
||||
'google',
|
||||
'anthropic',
|
||||
|
|
@ -139,15 +144,23 @@ export function formatToolContent(
|
|||
|
||||
resource: (item) => {
|
||||
const isUiResource = item.resource.uri.startsWith('ui://');
|
||||
const resourceText: string[] = [];
|
||||
|
||||
if (isUiResource) {
|
||||
uiResources.push(item.resource as UIResource);
|
||||
}
|
||||
const contentToHash = item.resource.text || item.resource.uri || '';
|
||||
const resourceId = generateResourceId(contentToHash);
|
||||
const uiResource: UIResource = {
|
||||
...item.resource,
|
||||
resourceId,
|
||||
};
|
||||
|
||||
const resourceText = [];
|
||||
if (!isUiResource && item.resource.text != null && item.resource.text) {
|
||||
uiResources.push(uiResource);
|
||||
resourceText.push(`UI Resource ID: ${resourceId}`);
|
||||
resourceText.push(`UI Resource Marker: \\ui{${resourceId}}`);
|
||||
} else if (item.resource.text != null && item.resource.text) {
|
||||
resourceText.push(`Resource Text: ${item.resource.text}`);
|
||||
}
|
||||
|
||||
if (item.resource.uri.length) {
|
||||
resourceText.push(`Resource URI: ${item.resource.uri}`);
|
||||
}
|
||||
|
|
@ -160,7 +173,10 @@ export function formatToolContent(
|
|||
if (item.resource.mimeType != null && item.resource.mimeType) {
|
||||
resourceText.push(`Resource MIME Type: ${item.resource.mimeType}`);
|
||||
}
|
||||
currentTextBlock += (currentTextBlock ? '\n\n' : '') + resourceText.join('\n');
|
||||
|
||||
if (resourceText.length) {
|
||||
currentTextBlock += (currentTextBlock ? '\n\n' : '') + resourceText.join('\n');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -174,6 +190,21 @@ export function formatToolContent(
|
|||
}
|
||||
}
|
||||
|
||||
if (uiResources.length > 0) {
|
||||
const uiInstructions = `
|
||||
|
||||
UI Resource Markers Available:
|
||||
- Each resource above includes a stable ID and a marker hint like \`\\ui{abc123}\`
|
||||
- You should usually introduce what you're showing before placing the marker
|
||||
- For a single resource: \\ui{resource-id}
|
||||
- For multiple resources shown separately: \\ui{resource-id-a} \\ui{resource-id-b}
|
||||
- For multiple resources in a carousel: \\ui{resource-id-a,resource-id-b,resource-id-c}
|
||||
- The UI will be rendered inline where you place the marker
|
||||
- Format: \\ui{resource-id} or \\ui{id1,id2,id3} using the IDs provided above`;
|
||||
|
||||
currentTextBlock += uiInstructions;
|
||||
}
|
||||
|
||||
if (CONTENT_ARRAY_PROVIDERS.has(provider) && currentTextBlock) {
|
||||
formattedContent.push({ type: 'text', text: currentTextBlock });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue