convertMessage method
Convert ChatMessage to OpenAI API format
Implementation
Map<String, dynamic> convertMessage(ChatMessage message) {
final result = <String, dynamic>{'role': message.role.name};
// Add name field if present (useful for system messages)
if (message.name != null) {
result['name'] = message.name;
}
switch (message.messageType) {
case TextMessage():
result['content'] = message.content;
break;
case ImageMessage(mime: final mime, data: final data):
// Handle base64 encoded images
final base64Data = base64Encode(data);
final imageDataUrl = 'data:${mime.mimeType};base64,$base64Data';
// Build content array with optional text + image
final contentArray = <Map<String, dynamic>>[];
// Add text content if present
if (message.content.isNotEmpty) {
if (config.useResponsesAPI) {
contentArray.add({
'type': 'input_text',
'text': message.content,
});
} else {
contentArray.add({
'type': 'text',
'text': message.content,
});
}
}
// Add image content
if (config.useResponsesAPI) {
contentArray.add({
'type': 'input_image',
'image_url': imageDataUrl,
});
} else {
contentArray.add({
'type': 'image_url',
'image_url': {'url': imageDataUrl},
});
}
result['content'] = contentArray;
break;
case ImageUrlMessage(url: final url):
// Build content array with optional text + image
final contentArray = <Map<String, dynamic>>[];
// Add text content if present
if (message.content.isNotEmpty) {
if (config.useResponsesAPI) {
contentArray.add({
'type': 'input_text',
'text': message.content,
});
} else {
contentArray.add({
'type': 'text',
'text': message.content,
});
}
}
// Add image content
if (config.useResponsesAPI) {
contentArray.add({
'type': 'input_image',
'image_url': url,
});
} else {
contentArray.add({
'type': 'image_url',
'image_url': {'url': url},
});
}
result['content'] = contentArray;
break;
case FileMessage(data: final data):
// Handle file messages (documents, audio, video, etc.)
final base64Data = base64Encode(data);
// Build content array with optional text + file
final contentArray = <Map<String, dynamic>>[];
// Add text content if present
if (message.content.isNotEmpty) {
if (config.useResponsesAPI) {
contentArray.add({
'type': 'input_text',
'text': message.content,
});
} else {
contentArray.add({
'type': 'text',
'text': message.content,
});
}
}
// Add file content
if (config.useResponsesAPI) {
// Responses API format: { type: 'input_file', file_data: '<base64>' }
contentArray.add({
'type': 'input_file',
'file_data': base64Data,
});
} else {
// Chat Completions API format: { type: 'file', file: { file_data: '<base64>' } }
contentArray.add({
'type': 'file',
'file': {
'file_data': base64Data,
},
});
}
result['content'] = contentArray;
break;
case ToolUseMessage(toolCalls: final toolCalls):
result['tool_calls'] = toolCalls.map((tc) => tc.toJson()).toList();
break;
case ToolResultMessage(results: final results):
// Tool results need to be converted to separate tool messages
// This case should not happen in normal message conversion
// as tool results are handled separately in buildRequestBody
result['content'] =
message.content.isNotEmpty ? message.content : 'Tool result';
result['tool_call_id'] = results.isNotEmpty ? results.first.id : null;
break;
}
return result;
}