MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / convertToOpenAiMessages

Function convertToOpenAiMessages

src/api/transform/openai-format.ts:322–597  ·  view source on GitHub ↗
(
	anthropicMessages: Anthropic.Messages.MessageParam[],
	options?: ConvertToOpenAiMessagesOptions,
)

Source from the content-addressed store, hash-verified

320}
321
322export function convertToOpenAiMessages(
323 anthropicMessages: Anthropic.Messages.MessageParam[],
324 options?: ConvertToOpenAiMessagesOptions,
325): OpenAI.Chat.ChatCompletionMessageParam[] {
326 const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = []
327
328 const mapReasoningDetails = (details: unknown): any[] | undefined => {
329 if (!Array.isArray(details)) {
330 return undefined
331 }
332
333 return details.map((detail: any) => {
334 // Strip `id` from openai-responses-v1 blocks because OpenAI's Responses API
335 // requires `store: true` to persist reasoning blocks. Since we manage
336 // conversation state client-side, we don't use `store: true`, and sending
337 // back the `id` field causes a 404 error.
338 if (detail?.format === "openai-responses-v1" && detail?.id) {
339 const { id, ...rest } = detail
340 return rest
341 }
342 return detail
343 })
344 }
345
346 // Use provided normalization function or identity function
347 const normalizeId = options?.normalizeToolCallId ?? ((id: string) => id)
348
349 for (const anthropicMessage of anthropicMessages) {
350 if (typeof anthropicMessage.content === "string") {
351 // Some upstream transforms (e.g. [`Task.buildCleanConversationHistory()`](src/core/task/Task.ts:4048))
352 // will convert a single text block into a string for compactness.
353 // If a message also contains reasoning_details (Gemini 3 / xAI / o-series, etc.),
354 // we must preserve it here as well.
355 const messageWithDetails = anthropicMessage as AssistantMessageWithReasoning
356 const baseMessage: OpenAI.Chat.ChatCompletionMessageParam & ReasoningPassthroughFields = {
357 role: anthropicMessage.role,
358 content: anthropicMessage.content,
359 }
360
361 if (anthropicMessage.role === "assistant") {
362 const mapped = mapReasoningDetails(messageWithDetails.reasoning_details)
363 if (mapped) {
364 baseMessage.reasoning_details = mapped
365 }
366 // Pass through reasoning_content for DeepSeek / Z.ai thinking mode.
367 if (typeof messageWithDetails.reasoning_content === "string" && messageWithDetails.reasoning_content) {
368 baseMessage.reasoning_content = messageWithDetails.reasoning_content
369 }
370 }
371
372 openAiMessages.push(baseMessage)
373 } else {
374 // image_url.url is base64 encoded image data
375 // ensure it contains the content-type of the image: data:image/png;base64,
376 /*
377 { role: "user", content: "" | { type: "text", text: string } | { type: "image_url", image_url: { url: string } } },
378 // content required unless tool_calls is present
379 { role: "assistant", content?: "" | null, tool_calls?: [{ id: "", function: { name: "", arguments: "" }, type: "function" }] },

Callers 13

createMessageMethod · 0.90
handleO3FamilyMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createMessageMethod · 0.90
createStreamFunction · 0.90
createMessageMethod · 0.90

Calls 3

mapReasoningDetailsFunction · 0.85
getReasoningBlockTextFunction · 0.85
forEachMethod · 0.80

Tested by

no test coverage detected