graphlit-client
Version:
Graphlit API Client for TypeScript
480 lines (479 loc) • 18.4 kB
JavaScript
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 };
}