UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera

243 lines (242 loc) 7.56 kB
class MCPContentProcessor { constructor(contentStorage, logger) { this.contentStorage = contentStorage; this.logger = logger; } analyzeResponse(response) { const contents = []; let totalSize = 0; this.extractContentFromResponse(response, contents); totalSize = contents.reduce((sum, content) => sum + content.sizeBytes, 0); const largestContentSize = contents.reduce((max, content) => Math.max(max, content.sizeBytes), 0); const shouldProcess = contents.some( (content) => this.contentStorage.shouldUseReference( typeof content.content === "string" ? content.content : JSON.stringify(content.content) ) ); return { shouldProcess, contents, totalSize, largestContentSize }; } async processResponse(response, serverName, toolName) { try { const analysis = this.analyzeResponse(response); if (!analysis.shouldProcess) { return { content: response, wasProcessed: false }; } const processedResponse = await this.createReferencedResponse( response, analysis, serverName, toolName ); return processedResponse; } catch (error) { this.logger.error("Error processing MCP response:", error); return { content: response, wasProcessed: false, errors: [error instanceof Error ? error.message : "Unknown processing error"] }; } } extractContentFromResponse(obj, contents) { if (obj === null || obj === void 0) { return; } if (Array.isArray(obj)) { obj.forEach((item) => this.extractContentFromResponse(item, contents)); return; } if (typeof obj === "object") { const record = obj; if (record.type === "text" && typeof record.text === "string") { contents.push({ content: record.text, type: "text", sizeBytes: Buffer.byteLength(record.text, "utf8"), mimeType: this.detectMimeType(record.text) }); return; } if (record.type === "image" && typeof record.data === "string") { contents.push({ content: record.data, type: "image", sizeBytes: Math.ceil(record.data.length * 0.75), mimeType: record.mimeType || "image/jpeg" }); return; } if (record.type === "resource" && record.resource) { const resourceStr = JSON.stringify(record.resource); contents.push({ content: resourceStr, type: "resource", sizeBytes: Buffer.byteLength(resourceStr, "utf8"), mimeType: "application/json" }); return; } Object.values(record).forEach((value) => this.extractContentFromResponse(value, contents)); return; } if (typeof obj === "string") { if (obj.length > 1e3) { contents.push({ content: obj, type: "text", sizeBytes: Buffer.byteLength(obj, "utf8"), mimeType: this.detectMimeType(obj) }); } } } async createReferencedResponse(originalResponse, analysis, serverName, toolName) { const processedResponse = this.deepClone(originalResponse); const errors = []; let referenceCreated = false; let totalReferenceSize = 0; for (const contentInfo of analysis.contents) { if (this.contentStorage.shouldUseReference( typeof contentInfo.content === "string" ? contentInfo.content : JSON.stringify(contentInfo.content) )) { try { const contentBuffer = Buffer.from( typeof contentInfo.content === "string" ? contentInfo.content : JSON.stringify(contentInfo.content), "utf8" ); const contentType = this.mapMimeTypeToContentType(contentInfo.mimeType); const metadata = { contentType, source: "mcp_tool", mcpToolName: `${serverName}::${toolName}`, tags: ["mcp_response", serverName, toolName] }; if (contentInfo.mimeType !== void 0) { metadata.mimeType = contentInfo.mimeType; } const reference = await this.contentStorage.storeContentIfLarge( contentBuffer, metadata ); if (reference) { this.replaceContentInResponse( processedResponse, contentInfo.content, this.createLightweightReference(reference) ); referenceCreated = true; totalReferenceSize += contentBuffer.length; } } catch (error) { errors.push(`Failed to create reference: ${error instanceof Error ? error.message : "Unknown error"}`); } } } const result = { content: processedResponse, wasProcessed: true, referenceCreated, originalSize: totalReferenceSize }; if (errors.length > 0) { result.errors = errors; } return result; } createLightweightReference(reference) { return { type: "content_reference", referenceId: reference.referenceId, preview: reference.preview, size: reference.metadata.sizeBytes, contentType: reference.metadata.contentType, format: "ref://{id}", _isReference: true }; } replaceContentInResponse(obj, oldContent, newContent) { if (obj === null || obj === void 0) { return; } if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { if (obj[i] === oldContent) { obj[i] = newContent; } else { this.replaceContentInResponse(obj[i], oldContent, newContent); } } return; } if (typeof obj === "object") { const record = obj; if (record.type === "text" && record.text === oldContent) { for (const key of Object.keys(record)) { delete record[key]; } for (const key of Object.keys(newContent)) { record[key] = newContent[key]; } return; } for (const key in record) { if (record[key] === oldContent) { record[key] = newContent; } else { this.replaceContentInResponse(record[key], oldContent, newContent); } } } } detectMimeType(content) { if (content.trim().startsWith("{") || content.trim().startsWith("[")) { return "application/json"; } if (content.includes("<html>") || content.includes("<!DOCTYPE")) { return "text/html"; } if (content.includes("# ") || content.includes("## ")) { return "text/markdown"; } return "text/plain"; } mapMimeTypeToContentType(mimeType) { if (!mimeType) return "text"; if (mimeType.startsWith("text/plain")) return "text"; if (mimeType === "application/json") return "json"; if (mimeType === "text/html") return "html"; if (mimeType === "text/markdown") return "markdown"; if (mimeType.startsWith("text/")) return "text"; return "binary"; } deepClone(obj) { if (obj === null || typeof obj !== "object") { return obj; } if (obj instanceof Date) { return new Date(obj.getTime()); } if (Array.isArray(obj)) { return obj.map((item) => this.deepClone(item)); } const cloned = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { cloned[key] = this.deepClone(obj[key]); } } return cloned; } } export { MCPContentProcessor }; //# sourceMappingURL=index27.js.map