UNPKG

@maximai/maxim-js

Version:

Maxim AI JS SDK. Visit https://getmaxim.ai for more info.

360 lines 20.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertOpenAIResponsesToCompletionResult = convertOpenAIResponsesToCompletionResult; exports.convertOpenAIResponsesMessagesToCompletionMessages = convertOpenAIResponsesMessagesToCompletionMessages; const uuid_1 = require("uuid"); /** * Convert an OpenAI Responses API object (or its `output` array) into a ChatCompletionResult. * * Accepts either the full Responses API response shape: * { * id, object: "response", created_at, model, output: Item[], usage?: { input_tokens?, output_tokens?, total_tokens? } * } * or a bare `output: Item[]` array. */ function convertOpenAIResponsesToCompletionResult(input) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18; const isFullResponse = input && typeof input === "object" && (Array.isArray(input.output) || Array.isArray(input.output_text)); const outputItems = Array.isArray(input) ? input : isFullResponse && Array.isArray(input.output) ? input.output : []; // Extract assistant text content (concatenate text parts) and tool calls if present let accumulatedText = []; let toolCalls = []; for (const item of outputItems) { // Responses API typically emits a `message` item containing `content` if (item && item.type === "message" && Array.isArray(item.content)) { for (const part of item.content) { // Common text part shape: { type: 'output_text', text: string } if (part && typeof part === "object") { if (typeof part.text === "string") { accumulatedText.push(part.text); continue; } // Some SDKs may surface plain text as { type: 'text', text } if (part.type === "text" && typeof part.text === "string") { accumulatedText.push(part.text); continue; } // Structured outputs may appear as an object; serialize for logging compatibility if (part.type && part.type.toString().toLowerCase().includes("json")) { const str = safeStringify((_b = (_a = part.object) !== null && _a !== void 0 ? _a : part.value) !== null && _b !== void 0 ? _b : part); if (str) accumulatedText.push(str); continue; } // Tool/function call variants (best-effort support) if ((part.type === "tool_call" || part.type === "tool-use" || part.type === "tool_use" || part.type === "function_call") && (part.name || ((_c = part.function) === null || _c === void 0 ? void 0 : _c.name))) { const id = part.id || part.tool_call_id || part.call_id || part.callId || (0, uuid_1.v4)(); const name = (_f = (_d = part.name) !== null && _d !== void 0 ? _d : (_e = part.function) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : "unknown_tool"; const rawArgs = (_k = (_h = (_g = part.arguments) !== null && _g !== void 0 ? _g : part.input) !== null && _h !== void 0 ? _h : (_j = part.function) === null || _j === void 0 ? void 0 : _j.arguments) !== null && _k !== void 0 ? _k : {}; const args = typeof rawArgs === "string" ? rawArgs : (_l = safeStringify(rawArgs)) !== null && _l !== void 0 ? _l : "{}"; toolCalls.push({ id, type: "function", function: { name, arguments: args } }); continue; } // Fallback: stringify anything else we don't recognize const fallback = safeStringify(part); if (fallback) accumulatedText.push(fallback); } } } // Top-level function/tool calls may also be emitted directly in `output`. // Normalize them into Chat Completions tool_calls for compatibility. if (item && typeof item === "object") { // function_call item from Responses API if (item.type === "function_call" && (item.name || ((_m = item.function) === null || _m === void 0 ? void 0 : _m.name))) { const id = item.callId || item.call_id || item.id || (0, uuid_1.v4)(); const name = (_q = (_o = item.name) !== null && _o !== void 0 ? _o : (_p = item.function) === null || _p === void 0 ? void 0 : _p.name) !== null && _q !== void 0 ? _q : "unknown_tool"; const rawArgs = (_u = (_s = (_r = item.arguments) !== null && _r !== void 0 ? _r : item.input) !== null && _s !== void 0 ? _s : (_t = item.function) === null || _t === void 0 ? void 0 : _t.arguments) !== null && _u !== void 0 ? _u : {}; const args = typeof rawArgs === "string" ? rawArgs : (_v = safeStringify(rawArgs)) !== null && _v !== void 0 ? _v : "{}"; toolCalls.push({ id, type: "function", function: { name, arguments: args } }); continue; } // Hosted/other tool call variants: map best-effort to function style for logging if ((item.type === "tool_call" || item.type === "hosted_tool_call" || item.type === "tool-use" || item.type === "tool_use") && (item.name || ((_w = item.function) === null || _w === void 0 ? void 0 : _w.name))) { const id = item.id || item.tool_call_id || item.call_id || item.callId || (0, uuid_1.v4)(); const name = (_z = (_x = item.name) !== null && _x !== void 0 ? _x : (_y = item.function) === null || _y === void 0 ? void 0 : _y.name) !== null && _z !== void 0 ? _z : "unknown_tool"; const rawArgs = (_5 = (_3 = (_1 = (_0 = item.arguments) !== null && _0 !== void 0 ? _0 : item.input) !== null && _1 !== void 0 ? _1 : (_2 = item.function) === null || _2 === void 0 ? void 0 : _2.arguments) !== null && _3 !== void 0 ? _3 : (_4 = item.providerData) === null || _4 === void 0 ? void 0 : _4.arguments) !== null && _5 !== void 0 ? _5 : {}; const args = typeof rawArgs === "string" ? rawArgs : (_6 = safeStringify(rawArgs)) !== null && _6 !== void 0 ? _6 : "{}"; toolCalls.push({ id, type: "function", function: { name, arguments: args } }); continue; } } } const message = { role: "assistant", content: accumulatedText.length ? accumulatedText.join("\n\n") : toolCalls.length ? null : "", ...(toolCalls.length ? { tool_calls: toolCalls } : {}), }; const createdSeconds = isFullResponse && typeof input.created_at === "number" ? input.created_at : Math.floor(Date.now() / 1000); const model = (isFullResponse && input.model) || "unknown"; const promptTokens = (_10 = (isFullResponse && ((_8 = (_7 = input.usage) === null || _7 === void 0 ? void 0 : _7.input_tokens) !== null && _8 !== void 0 ? _8 : (_9 = input.usage) === null || _9 === void 0 ? void 0 : _9.prompt_tokens))) !== null && _10 !== void 0 ? _10 : 0; const completionTokens = (_14 = (isFullResponse && ((_12 = (_11 = input.usage) === null || _11 === void 0 ? void 0 : _11.output_tokens) !== null && _12 !== void 0 ? _12 : (_13 = input.usage) === null || _13 === void 0 ? void 0 : _13.completion_tokens))) !== null && _14 !== void 0 ? _14 : 0; const totalTokens = (_17 = (isFullResponse && ((_16 = (_15 = input.usage) === null || _15 === void 0 ? void 0 : _15.total_tokens) !== null && _16 !== void 0 ? _16 : promptTokens + completionTokens))) !== null && _17 !== void 0 ? _17 : promptTokens + completionTokens; const completionResult = { id: (isFullResponse && input.id) || (0, uuid_1.v4)(), object: "chat_completion", created: createdSeconds, model, choices: [ { index: 0, message, logprobs: null, finish_reason: (_18 = inferFinishReason(input)) !== null && _18 !== void 0 ? _18 : "stop", }, ], usage: { prompt_tokens: promptTokens, completion_tokens: completionTokens, total_tokens: totalTokens, }, }; const modelParameters = extractModelParametersFromResponses(input); return { completionResult, modelParameters }; } /** * Convert an OpenAI Responses API-style messages array into a sequence of * CompletionRequest / ChatCompletionMessage items compatible with Chat Completions. * * Input examples include items like: * - { type: "message", role: "user" | "system" | "assistant", content: string | Part[] } * - { type: "function_call" | "tool_call" | "tool-use", name, arguments, callId?, id? } * - { type: "function_call_result" | "tool_result" | "tool-call-result", callId?, output } * * Mapping rules: * - Consecutive function/tool call items are batched into one assistant message with tool_calls. * - Each result item becomes a tool message with tool_call_id referring to its originating call. * - Assistant message content is null when tool_calls are present, otherwise text if available. */ function convertOpenAIResponsesMessagesToCompletionMessages(items) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w; const results = []; // Track pending tool calls to batch consecutive calls let pendingToolCalls = []; // Map to resolve tool_call_id for results const callKeyToId = new Map(); const flushPending = () => { if (pendingToolCalls.length === 0) return; results.push({ role: "assistant", content: null, tool_calls: pendingToolCalls }); pendingToolCalls = []; }; for (const item of items !== null && items !== void 0 ? items : []) { if (!item || typeof item !== "object") continue; const type = String(item.type || ""); // 1) Raw chat message if (type === "message") { flushPending(); const role = String(item.role || "user"); let textParts = []; const prevPendingCount = pendingToolCalls.length; // Parse message.content for text AND embedded tool/function calls if (Array.isArray(item.content)) { for (const part of item.content) { if (!part || typeof part !== "object") { const s = safeStringify(part); if (s) textParts.push(s); continue; } // Textual segments if (typeof part.text === "string") { textParts.push(part.text); continue; } if (typeof part.content === "string") { textParts.push(part.content); continue; } // Embedded tool/function call variants if ((part.type === "tool_call" || part.type === "tool-use" || part.type === "tool_use" || part.type === "function_call") && (part.name || ((_a = part.function) === null || _a === void 0 ? void 0 : _a.name))) { const id = part.id || part.tool_call_id || part.call_id || part.callId || (0, uuid_1.v4)(); const name = (_d = (_b = part.name) !== null && _b !== void 0 ? _b : (_c = part.function) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : "unknown_tool"; const rawArgs = (_h = (_f = (_e = part.arguments) !== null && _e !== void 0 ? _e : part.input) !== null && _f !== void 0 ? _f : (_g = part.function) === null || _g === void 0 ? void 0 : _g.arguments) !== null && _h !== void 0 ? _h : {}; const args = typeof rawArgs === "string" ? rawArgs : (_j = safeStringify(rawArgs)) !== null && _j !== void 0 ? _j : "{}"; pendingToolCalls.push({ id, type: "function", function: { name, arguments: args } }); const callKey = String(part.callId || part.call_id || part.id || id); callKeyToId.set(callKey, id); continue; } // Fallback: stringify structured content const fallback = safeStringify((_k = part.value) !== null && _k !== void 0 ? _k : part); if (fallback) textParts.push(fallback); } } else { // Non-array content: best-effort stringify or pass through if string if (typeof item.content === "string") { textParts.push(item.content); } else { const s = safeStringify(item.content); if (s) textParts.push(s); } } const finalText = textParts.join("\n\n"); if (role === "assistant") { // If this message contributed embedded tool calls, emit them together with remaining text if (pendingToolCalls.length > prevPendingCount) { results.push({ role: "assistant", content: finalText.length ? finalText : null, tool_calls: pendingToolCalls, }); pendingToolCalls = []; } else { results.push({ role: "assistant", content: finalText }); } } else { // user | system | tool | function results.push({ role: role, content: finalText }); } continue; } // 2) Function/tool call variants -> batch into assistant.tool_calls if (type === "function_call" || type === "tool_call" || type === "hosted_tool_call" || type === "tool-use" || type === "tool_use") { const id = item.callId || item.call_id || item.id || item.tool_call_id || (0, uuid_1.v4)(); const name = (_o = (_l = item.name) !== null && _l !== void 0 ? _l : (_m = item.function) === null || _m === void 0 ? void 0 : _m.name) !== null && _o !== void 0 ? _o : "unknown_tool"; const rawArgs = (_u = (_s = (_q = (_p = item.arguments) !== null && _p !== void 0 ? _p : item.input) !== null && _q !== void 0 ? _q : (_r = item.function) === null || _r === void 0 ? void 0 : _r.arguments) !== null && _s !== void 0 ? _s : (_t = item.providerData) === null || _t === void 0 ? void 0 : _t.arguments) !== null && _u !== void 0 ? _u : {}; const args = typeof rawArgs === "string" ? rawArgs : (_v = safeStringify(rawArgs)) !== null && _v !== void 0 ? _v : "{}"; pendingToolCalls.push({ id, type: "function", function: { name, arguments: args } }); // Use the most stable key present in result items to map back const callKey = String(item.callId || item.call_id || item.id || id); callKeyToId.set(callKey, id); continue; } // 3) Function/tool result variants -> flush calls then add tool message if (type === "function_call_result" || type === "tool_result" || type === "tool-call-result" || type === "tool_call_result") { flushPending(); const callKey = String(item.callId || item.call_id || item.tool_call_id || item.id || ""); const mappedId = callKeyToId.get(callKey) || callKey || (0, uuid_1.v4)(); const content = extractTextFromToolOutput(item); results.push({ role: "tool", content, tool_call_id: mappedId }); continue; } // 4) Fallback: unknown objects are stringified as a user message to preserve context flushPending(); const fallback = (_w = safeStringify(item)) !== null && _w !== void 0 ? _w : ""; if (fallback) results.push({ role: "user", content: fallback }); } flushPending(); return results; } function safeStringify(value) { try { if (typeof value === "string") return value; return JSON.stringify(value); } catch { return undefined; } } function inferFinishReason(responseLike) { if (!responseLike || typeof responseLike !== "object") return undefined; // Prefer per-item message status if available const items = Array.isArray(responseLike.output) ? responseLike.output : []; const msg = items.find((i) => i && i.type === "message"); if ((msg === null || msg === void 0 ? void 0 : msg.status) === "incomplete") return "length"; if ((msg === null || msg === void 0 ? void 0 : msg.status) === "completed") return "stop"; // Fall back to generic return undefined; } function extractModelParametersFromResponses(responseLike) { var _a; if (!responseLike || typeof responseLike !== "object") return {}; // Commonly surfaced parameters (best-effort — Responses API may not echo these back) const params = {}; const assignIfPresent = (key, value) => { if (value !== undefined && value !== null) params[key] = value; }; // Direct top-level in some SDKs assignIfPresent("temperature", responseLike.temperature); assignIfPresent("top_p", responseLike.top_p); assignIfPresent("max_tokens", (_a = responseLike.max_tokens) !== null && _a !== void 0 ? _a : responseLike.max_output_tokens); assignIfPresent("presence_penalty", responseLike.presence_penalty); assignIfPresent("frequency_penalty", responseLike.frequency_penalty); assignIfPresent("stop", responseLike.stop); assignIfPresent("seed", responseLike.seed); assignIfPresent("tool_choice", responseLike.tool_choice); if (responseLike.tools && Array.isArray(responseLike.tools) && responseLike.tools.length) { assignIfPresent("tools", responseLike.tools); } // Structured outputs: Chat Completions (response_format) vs Responses API (text.format) if (responseLike.response_format) { assignIfPresent("response_format", responseLike.response_format); } if (responseLike.text && typeof responseLike.text === "object" && responseLike.text.format) { assignIfPresent("response_format", responseLike.text.format); } // Reasoning configs (if present) if (responseLike.reasoning && typeof responseLike.reasoning === "object") { assignIfPresent("reasoning", responseLike.reasoning); } return params; } function extractTextFromMessageContent(content) { var _a; if (typeof content === "string") return content; if (!content) return ""; if (Array.isArray(content)) { const parts = []; for (const part of content) { if (!part || typeof part !== "object") continue; const anyPart = part; if (typeof anyPart.text === "string") { parts.push(anyPart.text); continue; } if (typeof anyPart.content === "string") { parts.push(anyPart.content); continue; } const s = safeStringify((_a = anyPart.value) !== null && _a !== void 0 ? _a : anyPart); if (s) parts.push(s); } return parts.join("\n\n"); } const s = safeStringify(content); return s !== null && s !== void 0 ? s : ""; } function extractTextFromToolOutput(item) { var _a; if (!item) return ""; if (typeof item.output === "string") return item.output; if (item.output && typeof item.output === "object") { if (typeof item.output.text === "string") return item.output.text; const s = safeStringify((_a = item.output.value) !== null && _a !== void 0 ? _a : item.output); if (s) return s; } if (typeof item.text === "string") return item.text; const s = safeStringify(item); return s !== null && s !== void 0 ? s : ""; } //# sourceMappingURL=utils.js.map