UNPKG

syia-mcp-utils

Version:

Global utility functions for MCP server

260 lines (259 loc) 9.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.filterResponseByCompanyImos = filterResponseByCompanyImos; exports.filterSingleResponseItem = filterSingleResponseItem; exports.hasUnauthorizedImos = hasUnauthorizedImos; exports.getFilteringStats = getFilteringStats; const config_js_1 = require("./config.js"); const logger_js_1 = require("./logger.js"); const imoUtils_js_1 = require("./imoUtils.js"); /** * IMO field names that should be checked for filtering */ const IMO_FIELD_NAMES = [ 'imo', 'vesselImo', 'imoNumber', 'IMO', 'vessel_imo', 'imo_number', 'vesselIMO' ]; /** * Check if an object contains any IMO field * @param obj - Object to check * @returns Object containing IMO field name and value, or null if none found */ function findImoField(obj) { if (!obj || typeof obj !== 'object') { return null; } for (const fieldName of IMO_FIELD_NAMES) { if (obj.hasOwnProperty(fieldName) && obj[fieldName] !== null && obj[fieldName] !== undefined) { return { fieldName, value: obj[fieldName] }; } } return null; } /** * Filter an array by removing items with unauthorized IMO numbers * @param array - Array to filter * @param stats - Statistics object to update * @returns Filtered array and updated statistics */ async function filterArrayByImo(array, stats) { logger_js_1.logger.debug(`Starting array filtering`, { arrayLength: array.length }); const filteredArray = []; for (const item of array) { stats.itemsProcessed++; // Check if this item has an IMO field at any level const hasUnauthorizedImo = await checkForUnauthorizedImo(item); if (hasUnauthorizedImo.found) { stats.itemsFiltered++; stats.unauthorizedImos.push(hasUnauthorizedImo.location); logger_js_1.logger.debug(`Filtered item with unauthorized IMO: ${hasUnauthorizedImo.location}`); } else { filteredArray.push(item); } } logger_js_1.logger.debug(`Array filtering complete`, { originalLength: array.length, filteredLength: filteredArray.length, itemsFiltered: stats.itemsFiltered }); return { filtered: filteredArray, stats }; } /** * Recursively check for unauthorized IMO numbers in an object * @param obj - Object to check * @returns Object with found flag and location string */ async function checkForUnauthorizedImo(obj) { if (!obj || typeof obj !== 'object') { return { found: false, location: '' }; } // Check direct IMO fields const imoField = findImoField(obj); if (imoField) { const companyName = (0, config_js_1.getConfig)().companyName || ''; if (!await (0, imoUtils_js_1.isValidImoForCompany)(imoField.value, companyName)) { return { found: true, location: `${imoField.fieldName}: ${imoField.value}` }; } } // Check nested objects and arrays for (const [key, value] of Object.entries(obj)) { if (Array.isArray(value)) { // Check each item in the array for (let i = 0; i < value.length; i++) { const result = await checkForUnauthorizedImo(value[i]); if (result.found) { return { found: true, location: `${key}[${i}].${result.location}` }; } } } else if (typeof value === 'object' && value !== null) { // Recursively check nested objects const result = await checkForUnauthorizedImo(value); if (result.found) { return { found: true, location: `${key}.${result.location}` }; } } } return { found: false, location: '' }; } /** * Filter response content recursively * @param content - Content to filter * @param stats - Statistics object to update * @returns Filtered content and updated statistics */ async function filterResponseContent(content, stats) { if (Array.isArray(content)) { const { filtered, stats: updatedStats } = await filterArrayByImo(content, stats); return { filtered, stats: updatedStats }; } else if (content && typeof content === 'object') { // Check if this object has unauthorized IMO const hasUnauthorizedImo = await checkForUnauthorizedImo(content); if (hasUnauthorizedImo.found) { stats.itemsFiltered++; stats.unauthorizedImos.push(hasUnauthorizedImo.location); logger_js_1.logger.debug(`Filtered object with unauthorized IMO: ${hasUnauthorizedImo.location}`); return { filtered: null, stats }; } // Recursively filter nested objects const filteredContent = {}; for (const [key, value] of Object.entries(content)) { const { filtered: filteredValue, stats: updatedStats } = await filterResponseContent(value, stats); if (filteredValue !== null) { filteredContent[key] = filteredValue; } } return { filtered: filteredContent, stats }; } return { filtered: content, stats }; } /** * Filter a ToolResponse by removing items with unauthorized IMO numbers * @param response - ToolResponse to filter * @returns Filtered ToolResponse */ async function filterResponseByCompanyImos(response) { const startTime = Date.now(); const stats = { itemsProcessed: 0, itemsFiltered: 0, unauthorizedImos: [], processingTimeMs: 0 }; try { // Skip filtering for admin companies const config = (0, config_js_1.getConfig)(); if ((0, imoUtils_js_1.shouldBypassImoFiltering)(config.companyName || '')) { logger_js_1.logger.debug('Admin company detected, skipping IMO filtering'); return response; } logger_js_1.logger.debug('Starting response filtering', { responseLength: response.length }); const filteredResponse = []; for (const item of response) { if (item.type === 'text' && item.text) { // Try to parse JSON content try { const parsedContent = JSON.parse(item.text); const { filtered: filteredContent, stats: updatedStats } = await filterResponseContent(parsedContent, stats); if (filteredContent !== null) { filteredResponse.push({ ...item, text: JSON.stringify(filteredContent, null, 2) }); } } catch (error) { // If not JSON, keep the text as is filteredResponse.push(item); } } else { // For other types (image, resource), check if they contain unauthorized IMO const hasUnauthorizedImo = await checkForUnauthorizedImo(item); if (!hasUnauthorizedImo.found) { filteredResponse.push(item); } else { stats.itemsFiltered++; stats.unauthorizedImos.push(hasUnauthorizedImo.location); } } } stats.processingTimeMs = Date.now() - startTime; logger_js_1.logger.info('Response filtering completed', { originalItems: response.length, filteredItems: filteredResponse.length, itemsFiltered: stats.itemsFiltered, processingTimeMs: stats.processingTimeMs, unauthorizedImos: stats.unauthorizedImos }); return filteredResponse; } catch (error) { logger_js_1.logger.error('Error during response filtering:', error); // Return original response if filtering fails return response; } } /** * Filter a single response item * @param item - Response item to filter * @returns Filtered item or null if unauthorized */ async function filterSingleResponseItem(item) { if (!item || typeof item !== 'object') { return item; } // Check if this item has unauthorized IMO const hasUnauthorizedImo = await checkForUnauthorizedImo(item); if (hasUnauthorizedImo.found) { logger_js_1.logger.debug(`Filtered single item with unauthorized IMO: ${hasUnauthorizedImo.location}`); return null; } return item; } /** * Check if a response contains unauthorized IMO numbers * @param response - ToolResponse to check * @returns True if unauthorized IMO found */ async function hasUnauthorizedImos(response) { for (const item of response) { const hasUnauthorizedImo = await checkForUnauthorizedImo(item); if (hasUnauthorizedImo.found) { return true; } } return false; } /** * Get filtering statistics from a response * @param response - ToolResponse to analyze * @returns FilterStats object */ async function getFilteringStats(response) { const stats = { itemsProcessed: 0, itemsFiltered: 0, unauthorizedImos: [], processingTimeMs: 0 }; for (const item of response) { stats.itemsProcessed++; const hasUnauthorizedImo = await checkForUnauthorizedImo(item); if (hasUnauthorizedImo.found) { stats.itemsFiltered++; stats.unauthorizedImos.push(hasUnauthorizedImo.location); } } return stats; }