UNPKG

graphlit-client

Version:
480 lines (479 loc) 18.4 kB
import { ConversationRoleTypes, } from "../generated/graphql-types.js"; /** * Format GraphQL conversation messages for OpenAI SDK */ export function formatMessagesForOpenAI(messages) { const formattedMessages = []; for (const message of messages) { if (!message.role) { continue; } // Allow messages with tool calls even if they have no text content const hasContent = message.message?.trim(); const hasToolCalls = message.toolCalls && message.toolCalls.length > 0; if (!hasContent && !hasToolCalls) { continue; } const trimmedMessage = message.message?.trim() || ""; switch (message.role) { case ConversationRoleTypes.System: formattedMessages.push({ role: "system", content: trimmedMessage, }); break; case ConversationRoleTypes.Assistant: const assistantMessage = { role: "assistant", }; // Only add content if there's actual text if (trimmedMessage) { assistantMessage.content = trimmedMessage; } // Add tool calls if present if (message.toolCalls && message.toolCalls.length > 0) { assistantMessage.tool_calls = message.toolCalls .filter((tc) => tc !== null) .map((toolCall) => ({ id: toolCall.id, type: "function", function: { name: toolCall.name, arguments: toolCall.arguments, }, })); } formattedMessages.push(assistantMessage); break; case ConversationRoleTypes.Tool: formattedMessages.push({ role: "tool", content: trimmedMessage, tool_call_id: message.toolCallId || "", }); break; default: // User messages // Check if this message has image data if (message.mimeType && message.data) { // Multi-modal message with image const contentParts = []; // Add text content if present if (trimmedMessage) { contentParts.push({ type: "text", text: trimmedMessage, }); } // Add image content contentParts.push({ type: "image_url", image_url: { url: `data:${message.mimeType};base64,${message.data}`, }, }); formattedMessages.push({ role: "user", content: contentParts, }); } else { // Text-only message formattedMessages.push({ role: "user", content: trimmedMessage, }); } break; } } return formattedMessages; } /** * Format GraphQL conversation messages for Anthropic SDK */ export function formatMessagesForAnthropic(messages) { let systemPrompt; const formattedMessages = []; for (const message of messages) { if (!message.role) continue; // Allow messages with tool calls even if they have no text content const hasContent = message.message?.trim(); const hasToolCalls = message.toolCalls && message.toolCalls.length > 0; if (!hasContent && !hasToolCalls) continue; const trimmedMessage = message.message?.trim() || ""; switch (message.role) { case ConversationRoleTypes.System: systemPrompt = trimmedMessage; break; case ConversationRoleTypes.Assistant: const content = []; // Add text content if (trimmedMessage) { content.push({ type: "text", text: trimmedMessage, }); } // Add tool uses if present if (message.toolCalls && message.toolCalls.length > 0) { for (const toolCall of message.toolCalls) { if (toolCall) { content.push({ type: "tool_use", id: toolCall.id, name: toolCall.name, input: toolCall.arguments ? JSON.parse(toolCall.arguments) : {}, }); } } } formattedMessages.push({ role: "assistant", content, }); break; case ConversationRoleTypes.Tool: // Anthropic expects tool responses as user messages with tool_result content blocks formattedMessages.push({ role: "user", content: [ { type: "tool_result", tool_use_id: message.toolCallId || "", content: trimmedMessage, }, ], }); break; default: // User messages // Check if this message has image data if (message.mimeType && message.data) { // Multi-modal message with image const contentParts = []; // Add text content if present if (trimmedMessage) { contentParts.push({ type: "text", text: trimmedMessage, }); } // Add image content contentParts.push({ type: "image", source: { type: "base64", media_type: message.mimeType, data: message.data, }, }); formattedMessages.push({ role: "user", content: contentParts, }); } else { // Text-only message formattedMessages.push({ role: "user", content: trimmedMessage, }); } break; } } const result = { system: systemPrompt, messages: formattedMessages }; return result; } /** * Format GraphQL conversation messages for Google SDK */ export function formatMessagesForGoogle(messages) { const formattedMessages = []; for (const message of messages) { if (!message.role) continue; // Allow messages with image data even if they have no text content const hasContent = message.message?.trim(); const hasImageData = message.mimeType && message.data; if (!hasContent && !hasImageData) continue; const trimmedMessage = message.message?.trim() || ""; switch (message.role) { case ConversationRoleTypes.System: // Google handles system prompts differently, usually as part of the first user message formattedMessages.push({ role: "user", parts: [{ text: trimmedMessage }], }); break; case ConversationRoleTypes.Assistant: const parts = []; // Add text content if (trimmedMessage) { parts.push({ text: trimmedMessage }); } // Add function calls if present if (message.toolCalls && message.toolCalls.length > 0) { for (const toolCall of message.toolCalls) { if (toolCall) { parts.push({ functionCall: { name: toolCall.name, args: toolCall.arguments ? JSON.parse(toolCall.arguments) : {}, }, }); } } } formattedMessages.push({ role: "model", parts, }); break; default: // User messages // Check if this message has image data if (message.mimeType && message.data) { // Multi-modal message with image const parts = []; // Add text content if present if (trimmedMessage) { parts.push({ text: trimmedMessage }); } // Add image content parts.push({ inlineData: { mimeType: message.mimeType, data: message.data, }, }); formattedMessages.push({ role: "user", parts, }); } else { // Text-only message formattedMessages.push({ role: "user", parts: [{ text: trimmedMessage }], }); } break; } } return formattedMessages; } /** * Format GraphQL conversation messages for Cohere SDK */ export function formatMessagesForCohere(messages) { const formattedMessages = []; for (const message of messages) { if (!message.role) continue; // Allow messages with tool calls even if they have no text content const hasContent = message.message?.trim(); const hasToolCalls = message.toolCalls && message.toolCalls.length > 0; if (!hasContent && !hasToolCalls) continue; const trimmedMessage = message.message?.trim() || ""; switch (message.role) { case ConversationRoleTypes.System: formattedMessages.push({ role: "SYSTEM", message: trimmedMessage, }); break; case ConversationRoleTypes.Assistant: const assistantMessage = { role: "CHATBOT", message: trimmedMessage, }; // Add tool calls if present if (message.toolCalls && message.toolCalls.length > 0) { assistantMessage.tool_calls = message.toolCalls .filter((tc) => tc !== null) .map((toolCall) => ({ id: toolCall.id, name: toolCall.name, parameters: toolCall.arguments ? JSON.parse(toolCall.arguments) : {}, })); } formattedMessages.push(assistantMessage); break; case ConversationRoleTypes.Tool: // Cohere expects tool results as TOOL messages formattedMessages.push({ role: "TOOL", message: trimmedMessage, tool_results: [ { call: { name: "", // Would need to be tracked from the tool call parameters: {}, }, outputs: [ { output: trimmedMessage, // Changed from 'text' to 'output' }, ], }, ], }); break; default: // User messages formattedMessages.push({ role: "USER", message: trimmedMessage, }); break; } } return formattedMessages; } /** * Format GraphQL conversation messages for Mistral SDK */ export function formatMessagesForMistral(messages) { const formattedMessages = []; for (const message of messages) { if (!message.role) continue; const hasContent = message.message?.trim(); const hasToolCalls = message.toolCalls && message.toolCalls.length > 0; if (!hasContent && !hasToolCalls) continue; const trimmedMessage = message.message?.trim() || ""; switch (message.role) { case ConversationRoleTypes.System: formattedMessages.push({ role: "system", content: trimmedMessage, }); break; case ConversationRoleTypes.Assistant: const assistantMessage = { role: "assistant", content: trimmedMessage, }; // Add tool calls if present if (message.toolCalls && message.toolCalls.length > 0) { assistantMessage.tool_calls = message.toolCalls .filter((tc) => tc !== null) .map((toolCall) => ({ id: toolCall.id, function: { name: toolCall.name, arguments: toolCall.arguments, }, })); } formattedMessages.push(assistantMessage); break; case ConversationRoleTypes.Tool: formattedMessages.push({ role: "tool", content: trimmedMessage, tool_call_id: message.toolCallId || "", }); break; default: // User messages // Check if this message has image data if (message.mimeType && message.data) { // Multi-modal message with image const contentParts = []; // Add text content if present if (trimmedMessage) { contentParts.push({ type: "text", text: trimmedMessage, }); } // Add image content contentParts.push({ type: "image_url", image_url: `data:${message.mimeType};base64,${message.data}`, }); formattedMessages.push({ role: "user", content: contentParts, }); } else { // Text-only message formattedMessages.push({ role: "user", content: trimmedMessage, }); } break; } } return formattedMessages; } /** * Format GraphQL conversation messages for Bedrock SDK (Claude models) */ export function formatMessagesForBedrock(messages) { let systemPrompt; const formattedMessages = []; for (const message of messages) { if (!message.role || !message.message?.trim()) continue; const trimmedMessage = message.message.trim(); switch (message.role) { case ConversationRoleTypes.System: systemPrompt = trimmedMessage; break; case ConversationRoleTypes.Assistant: formattedMessages.push({ role: "assistant", content: trimmedMessage, }); break; default: // User messages // Check if this message has image data if (message.mimeType && message.data) { // Multi-modal message with image const contentParts = []; // Add text content if present if (trimmedMessage) { contentParts.push({ type: "text", text: trimmedMessage, }); } // Add image content const format = message.mimeType.split("/")[1]; contentParts.push({ type: "image", image: { format, source: { bytes: message.data, }, }, }); formattedMessages.push({ role: "user", content: contentParts, }); } else { // Text-only message formattedMessages.push({ role: "user", content: trimmedMessage, }); } break; } } return { system: systemPrompt, messages: formattedMessages }; }