UNPKG

voyage-and-consumption-mcp-server

Version:

Voyage and consumption management server handling vessel voyages, fuel consumption, performance monitoring, and operational data with ERP access for data extraction

221 lines 7.52 kB
/** * Response Formatter Utility * * Centralizes response formatting logic that was duplicated across * 76+ response patterns in the codebase. * * This utility extracts common patterns: * - IMO-based title generation (20+ instances) * - JSON response formatting with type/format structure * - Dual response patterns (main + artifact data) * - Error response formatting (40+ instances) * - Consistent response object structures */ import { logger } from './logger.js'; // Error classes (re-exported for convenience) export class MissingParameterError extends Error { constructor(param, tool_name) { super(`Missing required parameter '${param}' for tool '${tool_name}'`); this.param = param; this.tool_name = tool_name; } } /** * Creates a formatted JSON response with consistent structure * @param data - The data to serialize as JSON * @param title - Optional title for the response * @returns Formatted response object */ export function formatJsonResponse(data, title) { const response = { type: "text", text: JSON.stringify(data, null, 2), format: "json" }; if (title) { response.title = title; } return response; } /** * Creates a simple text response * @param text - The text content * @param title - Optional title for the response * @returns Formatted response object */ export function formatTextResponse(text, title) { const response = { type: "text", text: text }; if (title) { response.title = title; } return response; } /** * Generates IMO-based titles with consistent formatting * @param action - The action description (e.g., "Fuel consumption data", "Live position and ETA") * @param imo - The IMO number (string or number) * @returns Formatted title string */ export function generateImoTitle(action, imo) { return `${action} for vessel with IMO ${imo}`; } /** * Generates query-based titles for search operations * @param action - The action description (e.g., "Smart voyage search results") * @param query - The search query * @returns Formatted title string */ export function generateQueryTitle(action, query) { return `${action} for '${query}'`; } /** * Creates a standard vessel data response with IMO-based title * @param data - The vessel data to return * @param action - The action description for the title * @param imo - The IMO number * @returns Formatted response array */ export function createVesselDataResponse(data, action, imo) { const title = generateImoTitle(action, imo); return [formatJsonResponse(data, title)]; } /** * Creates a dual response pattern (main data + artifact) * @param mainData - The primary response data * @param artifactData - The artifact data (usually with additional metadata) * @param action - The action description for titles * @param imo - The IMO number * @returns Array with both main and artifact responses */ export function createDualResponse(mainData, artifactData, action, imo) { const title = generateImoTitle(action, imo); return [ { type: "text", text: typeof mainData === 'string' ? mainData : JSON.stringify(mainData, null, 2), title: title, format: typeof mainData === 'string' ? undefined : "json" }, formatJsonResponse(artifactData, title) ]; } /** * Creates a search results response with conditional artifact * @param mainContent - The primary search results * @param artifactData - Optional artifact data * @param query - The search query * @param action - The action description * @returns Response array with optional artifact */ export function createSearchResponse(mainContent, artifactData, query, action = "Search results") { if (artifactData) { const artifactTitle = generateQueryTitle(action, query); const artifact = formatJsonResponse(artifactData, artifactTitle); return [mainContent, artifact]; } return [mainContent]; } /** * Creates an error response with consistent formatting * @param error - The error object or message * @param context - Optional context information * @param imo - Optional IMO number for context * @returns Formatted error response array */ export function createErrorResponse(error, context, imo) { let errorMessage; if (error instanceof MissingParameterError) { errorMessage = `Error: ${error.message}`; } else if (typeof error === 'string') { errorMessage = `Error: ${error}`; } else { const baseMessage = context ? `Failed to ${context}${imo ? ` for IMO ${imo}` : ''}: ${error}` : `Error: ${error.message}`; errorMessage = baseMessage; } logger.error(errorMessage); return [formatTextResponse(errorMessage)]; } /** * Creates a service-specific error response * @param error - The error object * @param serviceName - The name of the service that failed * @param imo - Optional IMO number for context * @returns Formatted error response array */ export function createServiceErrorResponse(error, serviceName, imo) { const errorMessage = `Error with ${serviceName} service: ${error.message}`; logger.error(errorMessage); return [formatTextResponse(errorMessage)]; } /** * Creates artifact data with standard structure * @param toolName - The name of the tool generating the artifact * @param url - Optional URL for the artifact * @returns Artifact object with standard metadata */ export function createArtifactData(toolName, url) { return { id: "msg_browser_ghi789", parentTaskId: `task_${toolName}_${Date.now()}`, timestamp: Math.floor(Date.now() / 1000), agent: { id: "agent_siya_browser", name: "SIYA", type: "qna" }, url: url || `https://example.com/${toolName}`, toolUsed: toolName, status: "success" }; } /** * Creates a historical data response with consistent formatting * @param documents - Array of historical data documents * @param action - The action description * @param imo - The IMO number * @param totalRecords - Optional total record count * @returns Formatted response for historical data */ export function createHistoricalDataResponse(documents, action, imo, totalRecords) { const response = { success: true, data: documents, total_records: totalRecords || documents.length, imo: imo }; return createVesselDataResponse(response, action, imo); } /** * Creates a casefile operation response * @param data - The casefile data * @param operation - The operation performed (e.g., "created", "updated") * @param casefileId - The casefile ID * @returns Formatted casefile response */ export function createCasefileResponse(data, operation, casefileId) { const title = `Casefile ${operation}: ${casefileId}`; return [formatJsonResponse(data, title)]; } /** * Wraps any response creation with error handling * @param responseCreator - Function that creates the response * @param errorContext - Context for error messages * @param imo - Optional IMO for error context * @returns Response array or error response */ export function withErrorHandling(responseCreator, errorContext, imo) { try { return responseCreator(); } catch (error) { return createErrorResponse(error, errorContext, imo); } } //# sourceMappingURL=response-formatter.js.map