|
|
@@ -0,0 +1,92 @@
|
|
|
+import { Anthropic } from "@anthropic-ai/sdk"
|
|
|
+import { Mistral } from "@mistralai/mistralai"
|
|
|
+import { AssistantMessage } from "@mistralai/mistralai/models/components/assistantmessage"
|
|
|
+import { SystemMessage } from "@mistralai/mistralai/models/components/systemmessage"
|
|
|
+import { ToolMessage } from "@mistralai/mistralai/models/components/toolmessage"
|
|
|
+import { UserMessage } from "@mistralai/mistralai/models/components/usermessage"
|
|
|
+
|
|
|
+export type MistralMessage =
|
|
|
+ | (SystemMessage & { role: "system" })
|
|
|
+ | (UserMessage & { role: "user" })
|
|
|
+ | (AssistantMessage & { role: "assistant" })
|
|
|
+ | (ToolMessage & { role: "tool" })
|
|
|
+
|
|
|
+export function convertToMistralMessages(anthropicMessages: Anthropic.Messages.MessageParam[]): MistralMessage[] {
|
|
|
+ const mistralMessages: MistralMessage[] = []
|
|
|
+ for (const anthropicMessage of anthropicMessages) {
|
|
|
+ if (typeof anthropicMessage.content === "string") {
|
|
|
+ mistralMessages.push({
|
|
|
+ role: anthropicMessage.role,
|
|
|
+ content: anthropicMessage.content,
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ if (anthropicMessage.role === "user") {
|
|
|
+ const { nonToolMessages, toolMessages } = anthropicMessage.content.reduce<{
|
|
|
+ nonToolMessages: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[]
|
|
|
+ toolMessages: Anthropic.ToolResultBlockParam[]
|
|
|
+ }>(
|
|
|
+ (acc, part) => {
|
|
|
+ if (part.type === "tool_result") {
|
|
|
+ acc.toolMessages.push(part)
|
|
|
+ } else if (part.type === "text" || part.type === "image") {
|
|
|
+ acc.nonToolMessages.push(part)
|
|
|
+ } // user cannot send tool_use messages
|
|
|
+ return acc
|
|
|
+ },
|
|
|
+ { nonToolMessages: [], toolMessages: [] },
|
|
|
+ )
|
|
|
+
|
|
|
+ if (nonToolMessages.length > 0) {
|
|
|
+ mistralMessages.push({
|
|
|
+ role: "user",
|
|
|
+ content: nonToolMessages.map((part) => {
|
|
|
+ if (part.type === "image") {
|
|
|
+ return {
|
|
|
+ type: "image_url",
|
|
|
+ imageUrl: {
|
|
|
+ url: `data:${part.source.media_type};base64,${part.source.data}`,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return { type: "text", text: part.text }
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else if (anthropicMessage.role === "assistant") {
|
|
|
+ const { nonToolMessages, toolMessages } = anthropicMessage.content.reduce<{
|
|
|
+ nonToolMessages: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[]
|
|
|
+ toolMessages: Anthropic.ToolUseBlockParam[]
|
|
|
+ }>(
|
|
|
+ (acc, part) => {
|
|
|
+ if (part.type === "tool_use") {
|
|
|
+ acc.toolMessages.push(part)
|
|
|
+ } else if (part.type === "text" || part.type === "image") {
|
|
|
+ acc.nonToolMessages.push(part)
|
|
|
+ } // assistant cannot send tool_result messages
|
|
|
+ return acc
|
|
|
+ },
|
|
|
+ { nonToolMessages: [], toolMessages: [] },
|
|
|
+ )
|
|
|
+
|
|
|
+ let content: string | undefined
|
|
|
+ if (nonToolMessages.length > 0) {
|
|
|
+ content = nonToolMessages
|
|
|
+ .map((part) => {
|
|
|
+ if (part.type === "image") {
|
|
|
+ return "" // impossible as the assistant cannot send images
|
|
|
+ }
|
|
|
+ return part.text
|
|
|
+ })
|
|
|
+ .join("\n")
|
|
|
+ }
|
|
|
+
|
|
|
+ mistralMessages.push({
|
|
|
+ role: "assistant",
|
|
|
+ content,
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return mistralMessages
|
|
|
+}
|