File size: 5,450 Bytes
f0743f4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | import { EToolResources } from 'librechat-data-provider';
import type { AgentToolResources, TFile } from 'librechat-data-provider';
/**
* Converts OCR tool resource to context tool resource in place.
* This modifies the input object directly (used for updateData in the handler).
*
* @param data - Object containing tool_resources and/or tools to convert
* @returns void - modifies the input object directly
*/
export function convertOcrToContextInPlace(data: {
tool_resources?: AgentToolResources;
tools?: string[];
}): void {
// Convert OCR to context in tool_resources
if (data.tool_resources?.ocr) {
if (!data.tool_resources.context) {
data.tool_resources.context = data.tool_resources.ocr;
} else {
// Merge OCR into existing context
if (data.tool_resources.ocr?.file_ids?.length) {
const existingFileIds = data.tool_resources.context.file_ids || [];
const ocrFileIds = data.tool_resources.ocr.file_ids || [];
data.tool_resources.context.file_ids = [...new Set([...existingFileIds, ...ocrFileIds])];
}
if (data.tool_resources.ocr?.files?.length) {
const existingFiles = data.tool_resources.context.files || [];
const ocrFiles = data.tool_resources.ocr.files || [];
const filesMap = new Map<string, TFile>();
[...existingFiles, ...ocrFiles].forEach((file) => {
if (file?.file_id) {
filesMap.set(file.file_id, file);
}
});
data.tool_resources.context.files = Array.from(filesMap.values());
}
}
delete data.tool_resources.ocr;
}
// Convert OCR to context in tools array
if (data.tools?.includes(EToolResources.ocr)) {
data.tools = data.tools.map((tool) =>
tool === EToolResources.ocr ? EToolResources.context : tool,
);
data.tools = [...new Set(data.tools)];
}
}
/**
* Merges tool resources from existing agent with incoming update data,
* converting OCR to context and handling deduplication.
* Used when existing agent has OCR that needs to be converted and merged with updateData.
*
* @param existingAgent - The existing agent data
* @param updateData - The incoming update data
* @returns Object with merged tool_resources and tools
*/
export function mergeAgentOcrConversion(
existingAgent: { tool_resources?: AgentToolResources; tools?: string[] },
updateData: { tool_resources?: AgentToolResources; tools?: string[] },
): { tool_resources?: AgentToolResources; tools?: string[] } {
if (!existingAgent.tool_resources?.ocr) {
return {};
}
const result: { tool_resources?: AgentToolResources; tools?: string[] } = {};
// Convert existing agent's OCR to context
result.tool_resources = { ...existingAgent.tool_resources };
if (!result.tool_resources.context) {
// Simple case: no context exists, just move ocr to context
result.tool_resources.context = result.tool_resources.ocr;
} else {
// Merge case: context already exists, merge both file_ids and files arrays
// Merge file_ids if they exist
if (result.tool_resources.ocr?.file_ids?.length) {
const existingFileIds = result.tool_resources.context.file_ids || [];
const ocrFileIds = result.tool_resources.ocr.file_ids || [];
result.tool_resources.context.file_ids = [...new Set([...existingFileIds, ...ocrFileIds])];
}
// Merge files array if it exists (already fetched files)
if (result.tool_resources.ocr?.files?.length) {
const existingFiles = result.tool_resources.context.files || [];
const ocrFiles = result.tool_resources.ocr?.files || [];
// Merge and deduplicate by file_id
const filesMap = new Map<string, TFile>();
[...existingFiles, ...ocrFiles].forEach((file) => {
if (file?.file_id) {
filesMap.set(file.file_id, file);
}
});
result.tool_resources.context.files = Array.from(filesMap.values());
}
}
// Remove the deprecated ocr resource
delete result.tool_resources.ocr;
// Update tools array: replace 'ocr' with 'context'
if (existingAgent.tools?.includes(EToolResources.ocr)) {
result.tools = existingAgent.tools.map((tool) =>
tool === EToolResources.ocr ? EToolResources.context : tool,
);
// Remove duplicates if context already existed
result.tools = [...new Set(result.tools)];
}
// Merge with any context that might already be in updateData (from incoming OCR conversion)
if (updateData.tool_resources?.context && result.tool_resources.context) {
// Merge the contexts
const mergedContext = { ...result.tool_resources.context };
// Merge file_ids
if (updateData.tool_resources.context.file_ids?.length) {
const existingIds = mergedContext.file_ids || [];
const newIds = updateData.tool_resources.context.file_ids || [];
mergedContext.file_ids = [...new Set([...existingIds, ...newIds])];
}
// Merge files
if (updateData.tool_resources.context.files?.length) {
const existingFiles = mergedContext.files || [];
const newFiles = updateData.tool_resources.context.files || [];
const filesMap = new Map<string, TFile>();
[...existingFiles, ...newFiles].forEach((file) => {
if (file?.file_id) {
filesMap.set(file.file_id, file);
}
});
mergedContext.files = Array.from(filesMap.values());
}
result.tool_resources.context = mergedContext;
}
return result;
}
|