UNPKG

@xynehq/jaf

Version:

Juspay Agent Framework - A purely functional agent framework with immutable state and composable tools

220 lines 8 kB
/** * JAF ADK Layer - Content System * * Functional content and message handling utilities */ // ========== Content Creation ========== export const createContent = (role, text, metadata) => ({ role, parts: [createTextPart(text)], metadata }); export const createUserMessage = (text, metadata) => createContent('user', text, metadata); export const createModelMessage = (text, metadata) => createContent('model', text, metadata); export const createSystemMessage = (text, metadata) => createContent('system', text, metadata); // ========== Part Creation ========== export const createTextPart = (text, metadata) => ({ type: 'text', text, metadata }); export const createImagePart = (data, metadata) => ({ type: 'image', data, metadata }); export const createAudioPart = (data, metadata) => ({ type: 'audio', data, metadata }); export const createFunctionCallPart = (functionCall, metadata) => ({ type: 'function_call', functionCall, metadata }); export const createFunctionResponsePart = (functionResponse, metadata) => ({ type: 'function_response', functionResponse, metadata }); // ========== Function Call/Response Creation ========== export const createFunctionCall = (id, name, args) => ({ id, name, args }); export const createFunctionResponse = (id, name, response, success = true, error) => ({ id, name, response, success, error }); // ========== Content Manipulation ========== export const addPart = (content, part) => ({ ...content, parts: [...content.parts, part] }); export const addTextPart = (content, text) => addPart(content, createTextPart(text)); export const addFunctionCall = (content, functionCall) => addPart(content, createFunctionCallPart(functionCall)); export const addFunctionResponse = (content, functionResponse) => addPart(content, createFunctionResponsePart(functionResponse)); // ========== Content Query Functions ========== export const getTextContent = (content) => { return content.parts .filter(part => part.type === 'text' && part.text) .map(part => part.text) .join(''); }; export const getFunctionCalls = (content) => { return content.parts .filter(part => part.type === 'function_call' && part.functionCall) .map(part => part.functionCall) .filter(Boolean); }; export const getFunctionResponses = (content) => { return content.parts .filter(part => part.type === 'function_response' && part.functionResponse) .map(part => part.functionResponse) .filter(Boolean); }; export const hasTextContent = (content) => { return content.parts.some(part => part.type === 'text' && part.text); }; export const hasFunctionCalls = (content) => { return content.parts.some(part => part.type === 'function_call'); }; export const hasFunctionResponses = (content) => { return content.parts.some(part => part.type === 'function_response'); }; // ========== Content Conversion ========== export const contentToString = (content) => { const textContent = getTextContent(content); const functionCalls = getFunctionCalls(content); const functionResponses = getFunctionResponses(content); let result = textContent; if (functionCalls.length > 0) { const callsStr = functionCalls .map(call => `[FUNCTION_CALL: ${call.name}(${JSON.stringify(call.args)})]`) .join(' '); result += (result ? ' ' : '') + callsStr; } if (functionResponses.length > 0) { const responsesStr = functionResponses .map(response => `[FUNCTION_RESPONSE: ${response.name} -> ${JSON.stringify(response.response)}]`) .join(' '); result += (result ? ' ' : '') + responsesStr; } return result; }; export const parseContent = (raw) => { if (typeof raw === 'string') { return createUserMessage(raw); } if (typeof raw === 'object' && raw !== null) { // Try to parse as existing Content object if ('role' in raw && 'parts' in raw) { return raw; } // Try to parse as simple message object if ('text' in raw || 'message' in raw) { const text = raw.text || raw.message; const role = raw.role || 'user'; return createContent(role, text); } } throw new Error(`Cannot parse content from: ${JSON.stringify(raw)}`); }; // ========== Content Validation ========== export const isValidContent = (content) => { if (typeof content !== 'object' || content === null) { return false; } const c = content; return (typeof c.role === 'string' && ['user', 'model', 'system'].includes(c.role) && Array.isArray(c.parts) && c.parts.every(isValidPart)); }; export const isValidPart = (part) => { if (typeof part !== 'object' || part === null) { return false; } const p = part; return (typeof p.type === 'string' && ['text', 'image', 'audio', 'function_call', 'function_response'].includes(p.type)); }; // ========== Content Utilities ========== export const mergeContent = (...contents) => { if (contents.length === 0) { return createUserMessage(''); } if (contents.length === 1) { return contents[0]; } const [first, ...rest] = contents; const allParts = [first, ...rest].flatMap(c => c.parts); return { ...first, parts: allParts }; }; export const cloneContent = (content) => ({ ...content, parts: content.parts.map(part => ({ ...part })), metadata: content.metadata ? { ...content.metadata } : undefined }); export const filterContentByRole = (contents, role) => { return contents.filter(content => content.role === role); }; export const getLastUserMessage = (contents) => { const userMessages = filterContentByRole(contents, 'user'); return userMessages.length > 0 ? userMessages[userMessages.length - 1] : null; }; export const getLastModelMessage = (contents) => { const modelMessages = filterContentByRole(contents, 'model'); return modelMessages.length > 0 ? modelMessages[modelMessages.length - 1] : null; }; // ========== Content Statistics ========== export const getContentStats = (content) => { const textParts = content.parts.filter(p => p.type === 'text').length; const imageParts = content.parts.filter(p => p.type === 'image').length; const audioParts = content.parts.filter(p => p.type === 'audio').length; const functionCallParts = content.parts.filter(p => p.type === 'function_call').length; const functionResponseParts = content.parts.filter(p => p.type === 'function_response').length; const textLength = getTextContent(content).length; return { totalParts: content.parts.length, textParts, imageParts, audioParts, functionCallParts, functionResponseParts, textLength, hasMedia: imageParts > 0 || audioParts > 0, hasFunctions: functionCallParts > 0 || functionResponseParts > 0 }; }; export const getConversationStats = (contents) => { const userMessages = filterContentByRole(contents, 'user').length; const modelMessages = filterContentByRole(contents, 'model').length; const systemMessages = filterContentByRole(contents, 'system').length; const totalTextLength = contents .map(getTextContent) .reduce((sum, text) => sum + text.length, 0); const totalFunctionCalls = contents .flatMap(getFunctionCalls).length; const totalFunctionResponses = contents .flatMap(getFunctionResponses).length; return { totalMessages: contents.length, userMessages, modelMessages, systemMessages, totalTextLength, totalFunctionCalls, totalFunctionResponses, averageMessageLength: contents.length > 0 ? totalTextLength / contents.length : 0 }; }; //# sourceMappingURL=index.js.map