UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

136 lines (135 loc) 5.1 kB
import { c as isRecord } from "./utils-CCC-BEJH.js"; import { r as ensureGlobalUndiciEnvProxyDispatcher } from "./undici-global-dispatcher-DTahNL39.js"; import { n as normalizeSecretInput } from "./normalize-secret-input-OwRUfByL.js"; //#region src/agents/minimax-vlm.ts /** * Adapts MiniMax VLM image-understanding requests for agent image inputs. */ const MINIMAX_VLM_ERROR_BODY_MAX_BYTES = 8 * 1024; const MINIMAX_VLM_ERROR_BODY_MAX_CHARS = 400; async function readErrorBodySnippet(res) { try { const body = res.body; if (!body || typeof body.getReader !== "function") return (await res.text()).slice(0, MINIMAX_VLM_ERROR_BODY_MAX_CHARS); const reader = body.getReader(); const chunks = []; let total = 0; let truncated = false; try { while (true) { const { done, value } = await reader.read(); if (done || !value?.byteLength) break; const remaining = MINIMAX_VLM_ERROR_BODY_MAX_BYTES - total; if (remaining <= 0) { truncated = true; break; } if (value.byteLength > remaining) { chunks.push(value.subarray(0, remaining)); total += remaining; truncated = true; break; } chunks.push(value); total += value.byteLength; if (total >= MINIMAX_VLM_ERROR_BODY_MAX_BYTES) { truncated = true; break; } } } finally { if (truncated) await reader.cancel().catch(() => void 0); try { reader.releaseLock(); } catch {} } return new TextDecoder().decode(Buffer.concat(chunks, total)).slice(0, MINIMAX_VLM_ERROR_BODY_MAX_CHARS); } catch { return ""; } } function isMinimaxVlmProvider(provider) { const normalized = provider.trim().toLowerCase(); return normalized === "minimax" || normalized === "minimax-cn" || normalized === "minimax-portal" || normalized === "minimax-portal-cn"; } function isMinimaxVlmModel(provider, modelId) { return isMinimaxVlmProvider(provider) && modelId.trim() === "MiniMax-VL-01"; } function isMinimaxCnProvider(provider) { const normalized = provider?.trim().toLowerCase(); return normalized === "minimax-cn" || normalized === "minimax-portal-cn"; } function coerceApiHost(params) { const env = params.env ?? process.env; const defaultHost = isMinimaxCnProvider(params.provider) ? "https://api.minimaxi.com" : "https://api.minimax.io"; const raw = params.apiHost?.trim() || env.MINIMAX_API_HOST?.trim() || params.modelBaseUrl?.trim() || defaultHost; try { return new URL(raw).origin; } catch {} if (/^[a-z][a-z\d+.-]*:\/\//i.test(raw)) return defaultHost; try { return new URL(`https://${raw}`).origin; } catch { return defaultHost; } } function pickString(rec, key) { const v = rec[key]; return typeof v === "string" ? v : ""; } async function minimaxUnderstandImage(params) { const apiKey = normalizeSecretInput(params.apiKey); if (!apiKey) throw new Error("MiniMax VLM: apiKey required"); const prompt = params.prompt.trim(); if (!prompt) throw new Error("MiniMax VLM: prompt required"); const imageDataUrl = params.imageDataUrl.trim(); if (!imageDataUrl) throw new Error("MiniMax VLM: imageDataUrl required"); if (!/^data:image\/(png|jpeg|webp);base64,/i.test(imageDataUrl)) throw new Error("MiniMax VLM: imageDataUrl must be a base64 data:image/(png|jpeg|webp) URL"); const host = coerceApiHost({ apiHost: params.apiHost, modelBaseUrl: params.modelBaseUrl, provider: params.provider }); const url = new URL("/v1/coding_plan/vlm", host).toString(); ensureGlobalUndiciEnvProxyDispatcher(); const timeoutMs = typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs) && params.timeoutMs > 0 ? Math.floor(params.timeoutMs) : 6e4; const res = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", "MM-API-Source": "OpenClaw" }, signal: AbortSignal.timeout(timeoutMs), body: JSON.stringify({ prompt, image_url: imageDataUrl }) }); const traceId = res.headers.get("Trace-Id") ?? ""; if (!res.ok) { const body = await readErrorBodySnippet(res); const trace = traceId ? ` Trace-Id: ${traceId}` : ""; throw new Error(`MiniMax VLM request failed (${res.status} ${res.statusText}).${trace}${body ? ` Body: ${body}` : ""}`); } const json = await res.json().catch(() => null); if (!isRecord(json)) { const trace = traceId ? ` Trace-Id: ${traceId}` : ""; throw new Error(`MiniMax VLM response was not JSON.${trace}`); } const baseResp = isRecord(json.base_resp) ? json.base_resp : {}; const code = typeof baseResp.status_code === "number" ? baseResp.status_code : -1; if (code !== 0) { const msg = (baseResp.status_msg ?? "").trim(); const trace = traceId ? ` Trace-Id: ${traceId}` : ""; throw new Error(`MiniMax VLM API error (${code})${msg ? `: ${msg}` : ""}.${trace}`); } const content = pickString(json, "content").trim(); if (!content) { const trace = traceId ? ` Trace-Id: ${traceId}` : ""; throw new Error(`MiniMax VLM returned no content.${trace}`); } return content; } //#endregion export { isMinimaxVlmProvider as n, minimaxUnderstandImage as r, isMinimaxVlmModel as t };