Files
xiaoli-cli/plugins/operit/minimax_draw.ts
T
xiaoli-cli bot dfe21298b9 release: v5.4.2 - terminal模拟器 + Operit桥接
新增插件:
- terminal: 持久交互式终端,纯标准库,全平台,13个测试
- operit_bridge: Operit AI工具格式桥接,47个脚本288个工具,12个测试

其他:
- plugins/operit/: 47个Operit官方脚本
- 更新plugin_registry.json/plugins_config.py
- 更新about.txt/CHANGELOG.md至v5.4.2
2026-06-23 08:50:15 +00:00

692 lines
29 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* METADATA
{
"name": "minimax_draw",
"display_name": {
"zh": "MiniMax 绘图",
"en": "MiniMax Draw"
},
"description": {
"zh": "使用 MiniMax 官方图像生成接口 (/v1/image_generation) 生成图片,支持文生图和带参考图的生图;结果保存到本地 /sdcard/Download/Operit/plugins/draw/minimax_draw/draws/ 目录,并返回 Markdown 图片提示。",
"en": "Generate images with the official MiniMax image generation API (/v1/image_generation). Supports text-to-image and reference-image generation. Saves results to /sdcard/Download/Operit/plugins/draw/minimax_draw/draws/ and returns Markdown image hints."
},
"category": "Draw",
"env": [
{
"name": "MINIMAX_API_KEY",
"description": {
"zh": "MiniMax API Key(必填)",
"en": "MiniMax API key (required)"
},
"required": true
},
{
"name": "MINIMAX_API_BASE_URL",
"description": {
"zh": "MiniMax API Base URL(可选;默认 https://api.minimaxi.com,国际站可改为 https://api.minimax.io)",
"en": "MiniMax API base URL (optional; defaults to https://api.minimaxi.com, international users can use https://api.minimax.io)"
},
"required": false
},
{
"name": "MINIMAX_IMAGE_MODEL",
"description": {
"zh": "默认图片模型(可选;未传 model 时使用,默认 image-01)",
"en": "Default image model (optional; used when model is omitted, default image-01)"
},
"required": false
},
{
"name": "BEEIMG_API_KEY",
"description": {
"zh": "BeeIMG API Key(可选;仅当 image_paths 传本地参考图路径时需要,用于先上传到公网图床)",
"en": "BeeIMG API key (optional; only needed when image_paths is used so local reference images can be uploaded first)"
},
"required": false
}
],
"tools": [
{
"name": "draw_image",
"description": {
"zh": "根据提示词调用 MiniMax 官方绘图接口生成图片,支持文生图和参考图生图,保存到本地并返回 Markdown 图片提示。",
"en": "Generate images with the official MiniMax image API using a prompt. Supports text-to-image and reference-image generation, saves locally, and returns Markdown image hints."
},
"parameters": [
{ "name": "prompt", "description": { "zh": "绘图提示词(中文或英文)", "en": "Image prompt (Chinese or English)" }, "type": "string", "required": true },
{ "name": "model", "description": { "zh": "模型名称(可选;不传则使用环境变量 MINIMAX_IMAGE_MODEL,否则默认 image-01)", "en": "Model name (optional; falls back to MINIMAX_IMAGE_MODEL, then image-01)" }, "type": "string", "required": false },
{ "name": "aspect_ratio", "description": { "zh": "输出比例,可选 1:1、16:9、4:3、3:2、2:3、3:4、9:16、21:9;21:9 仅 image-01 支持", "en": "Aspect ratio. Supported: 1:1, 16:9, 4:3, 3:2, 2:3, 3:4, 9:16, 21:9. 21:9 is only supported by image-01." }, "type": "string", "required": false },
{ "name": "width", "description": { "zh": "输出宽度(可选;仅 image-01 支持;需与 height 一起传,范围 512-2048 且为 8 的倍数)", "en": "Output width (optional; image-01 only; must be provided together with height, range 512-2048 and multiple of 8)" }, "type": "number", "required": false },
{ "name": "height", "description": { "zh": "输出高度(可选;仅 image-01 支持;需与 width 一起传,范围 512-2048 且为 8 的倍数)", "en": "Output height (optional; image-01 only; must be provided together with width, range 512-2048 and multiple of 8)" }, "type": "number", "required": false },
{ "name": "n", "description": { "zh": "生成图片数量,范围 1-9,默认 1", "en": "Number of images to generate, range 1-9, default 1" }, "type": "number", "required": false },
{ "name": "response_format", "description": { "zh": "返回格式,可选 url 或 base64;默认 base64(更适合直接保存到本地)", "en": "Response format: url or base64. Defaults to base64 for direct local saving." }, "type": "string", "required": false },
{ "name": "prompt_optimizer", "description": { "zh": "是否启用提示词优化(可选)", "en": "Enable prompt optimizer (optional)" }, "type": "boolean", "required": false },
{ "name": "aigc_watermark", "description": { "zh": "是否添加 AIGC 水印(可选)", "en": "Add AIGC watermark (optional)" }, "type": "boolean", "required": false },
{ "name": "seed", "description": { "zh": "随机种子(可选)", "en": "Seed (optional)" }, "type": "number", "required": false },
{ "name": "image_urls", "description": { "zh": "参考图公网 URL 数组(可选;图生图用)。支持字符串数组、JSON 字符串或逗号分隔字符串", "en": "Reference image public URL list (optional; for reference-image generation). Accepts string array, JSON string, or comma-separated string." }, "type": "array", "required": false },
{ "name": "image_paths", "description": { "zh": "参考图本地路径数组(可选;会先上传到图床再提交给 MiniMax)。支持字符串数组、JSON 字符串或逗号分隔字符串", "en": "Reference local image path list (optional; local images are uploaded first before calling MiniMax). Accepts string array, JSON string, or comma-separated string." }, "type": "array", "required": false },
{ "name": "file_name", "description": { "zh": "自定义本地文件名(不含扩展名)", "en": "Custom local output file name without extension" }, "type": "string", "required": false },
{ "name": "api_base_url", "description": { "zh": "自定义 MiniMax API Base URL(可选)", "en": "Custom MiniMax API base URL (optional)" }, "type": "string", "required": false }
]
}
]
}*/
/// <reference path="./types/index.d.ts" />
const minimaxDraw = (function () {
const HTTP_TIMEOUT_MS = 600000;
const client = OkHttp.newBuilder()
.connectTimeout(HTTP_TIMEOUT_MS)
.readTimeout(HTTP_TIMEOUT_MS)
.writeTimeout(HTTP_TIMEOUT_MS)
.build();
const DEFAULT_API_BASE_URL = "https://api.minimaxi.com";
const DEFAULT_MODEL = "image-01";
const DEFAULT_RESPONSE_FORMAT = "base64";
const DEFAULT_IMAGE_COUNT = 1;
const DEFAULT_BASE64_EXTENSION = "jpeg";
const SUPPORTED_ASPECT_RATIOS = ["1:1", "16:9", "4:3", "3:2", "2:3", "3:4", "9:16", "21:9"];
const BEEIMG_UPLOAD_ENDPOINT = "https://beeimg.com/api/upload/file/json/";
const DRAW_ROOT_DIR = getPluginConfigDir("draw");
const STORAGE_DIR = `${DRAW_ROOT_DIR}/minimax_draw`;
const DRAWS_DIR = `${STORAGE_DIR}/draws`;
function isRecord(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function getErrorMessage(error) {
if (error instanceof Error) return error.message;
return String(error);
}
function getApiKey() {
const apiKey = String(getEnv("MINIMAX_API_KEY") || "").trim();
if (!apiKey) {
throw new Error("MINIMAX_API_KEY 未配置,请先在环境变量中设置 MiniMax API Key。");
}
return apiKey;
}
function joinUrl(baseUrl, path) {
const normalizedBase = String(baseUrl || "").endsWith("/") ? String(baseUrl || "") : `${baseUrl}/`;
const normalizedPath = String(path || "").startsWith("/") ? String(path).slice(1) : String(path || "");
return `${normalizedBase}${normalizedPath}`;
}
function getApiBaseUrl(customBaseUrl) {
const fromParam = String(customBaseUrl || "").trim();
if (fromParam) return fromParam;
const fromEnv = String(getEnv("MINIMAX_API_BASE_URL") || "").trim();
if (fromEnv) return fromEnv;
return DEFAULT_API_BASE_URL;
}
function getImageEndpoint(baseUrl) {
const trimmed = String(baseUrl || "").trim();
if (!trimmed) return joinUrl(DEFAULT_API_BASE_URL, "v1/image_generation");
if (trimmed.includes("/v1/image_generation")) return trimmed;
if (trimmed.endsWith("/v1")) return joinUrl(trimmed, "image_generation");
if (trimmed.endsWith("/v1/")) return joinUrl(trimmed, "image_generation");
return joinUrl(trimmed, "v1/image_generation");
}
function resolveModel(model) {
const fromParam = String(model || "").trim();
if (fromParam) return fromParam;
const fromEnv = String(getEnv("MINIMAX_IMAGE_MODEL") || "").trim();
if (fromEnv) return fromEnv;
return DEFAULT_MODEL;
}
function sanitizeFileName(name, fallbackPrefix) {
const safe = String(name || "").replace(/[\\/:*?"<>|]/g, "_").trim();
if (!safe) return `${fallbackPrefix}_${Date.now()}`;
return safe.substring(0, 80);
}
function buildFileBaseName(prompt, customName, fallbackPrefix) {
const fromCustom = String(customName || "").trim();
if (fromCustom) {
return sanitizeFileName(fromCustom, fallbackPrefix);
}
const rawPrompt = String(prompt || "").trim();
const shortPrompt = rawPrompt.length > 40 ? `${rawPrompt.substring(0, 40)}...` : rawPrompt;
return `${sanitizeFileName(shortPrompt || fallbackPrefix, fallbackPrefix)}_${Date.now()}`;
}
async function ensureDirectories() {
const dirs = [DRAW_ROOT_DIR, STORAGE_DIR, DRAWS_DIR];
for (const dir of dirs) {
try {
const result = await Tools.Files.mkdir(dir);
if (!result.successful) {
console.warn(`创建目录失败(可能已存在): ${dir} -> ${result.details}`);
}
} catch (error) {
console.warn(`创建目录异常: ${dir} -> ${getErrorMessage(error)}`);
}
}
}
function parsePositiveInteger(value, fieldName, options?) {
const hasDefault = !!options && Object.prototype.hasOwnProperty.call(options, "defaultValue");
const defaultValue = hasDefault ? options.defaultValue : undefined;
if (value === undefined || value === null || value === "") {
return defaultValue;
}
const numberValue = typeof value === "number" ? value : Number(String(value));
if (!Number.isFinite(numberValue) || numberValue <= 0 || !Number.isInteger(numberValue)) {
throw new Error(`${fieldName} 必须是正整数。`);
}
if (options && options.min !== undefined && numberValue < options.min) {
throw new Error(`${fieldName} 不能小于 ${options.min}。`);
}
if (options && options.max !== undefined && numberValue > options.max) {
throw new Error(`${fieldName} 不能大于 ${options.max}。`);
}
return numberValue;
}
function parseInteger(value, fieldName) {
if (value === undefined || value === null || value === "") {
return undefined;
}
const numberValue = typeof value === "number" ? value : Number(String(value));
if (!Number.isFinite(numberValue) || !Number.isInteger(numberValue)) {
throw new Error(`${fieldName} 必须是整数。`);
}
return numberValue;
}
function parseBoolean(value, fieldName) {
if (value === undefined || value === null || value === "") {
return undefined;
}
if (typeof value === "boolean") {
return value;
}
const normalized = String(value).trim().toLowerCase();
if (normalized === "true" || normalized === "1" || normalized === "yes") {
return true;
}
if (normalized === "false" || normalized === "0" || normalized === "no") {
return false;
}
throw new Error(`${fieldName} 必须是布尔值。`);
}
function normalizeResponseFormat(value) {
const normalized = String(value || DEFAULT_RESPONSE_FORMAT).trim().toLowerCase();
if (normalized !== "url" && normalized !== "base64") {
throw new Error("response_format 仅支持 url 或 base64。");
}
return normalized;
}
function normalizeAspectRatio(model, value) {
const normalized = String(value || "").trim();
if (!normalized) return undefined;
if (!SUPPORTED_ASPECT_RATIOS.includes(normalized)) {
throw new Error(`aspect_ratio 仅支持 ${SUPPORTED_ASPECT_RATIOS.join("、")}。`);
}
if (normalized === "21:9" && String(model || "").trim() !== "image-01") {
throw new Error("aspect_ratio=21:9 仅支持 model=image-01。");
}
return normalized;
}
function normalizeDimensions(model, widthValue, heightValue, aspectRatio) {
if (aspectRatio) {
return {
width: undefined,
height: undefined
};
}
const width = parsePositiveInteger(widthValue, "width");
const height = parsePositiveInteger(heightValue, "height");
if (width === undefined && height === undefined) {
return {
width: undefined,
height: undefined
};
}
if (width === undefined || height === undefined) {
throw new Error("width 和 height 需要同时传入。");
}
if (String(model || "").trim() !== "image-01") {
throw new Error("width 和 height 仅支持 model=image-01。");
}
if (width < 512 || width > 2048 || width % 8 !== 0) {
throw new Error("width 需要在 512-2048 之间,且必须为 8 的倍数。");
}
if (height < 512 || height > 2048 || height % 8 !== 0) {
throw new Error("height 需要在 512-2048 之间,且必须为 8 的倍数。");
}
return { width, height };
}
function parseStringList(value, fieldName) {
if (value === undefined || value === null || value === "") {
return [];
}
if (Array.isArray(value)) {
return value
.map(item => String(item || "").trim())
.filter(item => item.length > 0);
}
if (typeof value === "string") {
const trimmed = value.trim();
if (!trimmed) return [];
try {
const parsed = JSON.parse(trimmed);
if (Array.isArray(parsed)) {
return parsed
.map(item => String(item || "").trim())
.filter(item => item.length > 0);
}
} catch {
// ignore and try comma-separated parsing
}
return trimmed
.split(",")
.map(item => item.trim())
.filter(item => item.length > 0);
}
throw new Error(`${fieldName} 必须是字符串数组、JSON 字符串或逗号分隔字符串。`);
}
function isProbablyUrl(value) {
return /^https?:\/\//i.test(String(value || "").trim());
}
function getBeeimgApiKey() {
return String(getEnv("BEEIMG_API_KEY") || "").trim();
}
function guessMimeTypeFromPath(filePath) {
const lower = String(filePath || "").toLowerCase();
if (lower.endsWith(".png")) return "image/png";
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
if (lower.endsWith(".webp")) return "image/webp";
if (lower.endsWith(".gif")) return "image/gif";
return "application/octet-stream";
}
async function uploadImageToBeeimg(filePath) {
const exists = await Tools.Files.exists(filePath);
if (!exists.exists) {
throw new Error(`参考图文件不存在: ${filePath}`);
}
const apiKey = getBeeimgApiKey();
if (!apiKey) {
throw new Error("使用 image_paths 需要配置 BEEIMG_API_KEY,用于先把本地参考图上传到公网图床。");
}
const response = await Tools.Net.uploadFile({
url: BEEIMG_UPLOAD_ENDPOINT,
method: "POST",
form_data: {
apikey: apiKey
},
files: [
{
field_name: "file",
file_path: filePath,
content_type: guessMimeTypeFromPath(filePath)
}
]
});
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new Error(`BeeIMG 上传失败: HTTP ${response.statusCode} - ${response.content}`);
}
let parsed;
try {
parsed = JSON.parse(response.content);
} catch (error) {
throw new Error(`解析 BeeIMG 响应失败: ${getErrorMessage(error)}`);
}
const files = isRecord(parsed) && isRecord(parsed.files) ? parsed.files : null;
const fileUrl = files && files.url ? String(files.url).trim() : "";
const code = files && files.code !== undefined ? String(files.code) : "";
const status = files && files.status ? String(files.status) : "";
if (!fileUrl || (code !== "200" && code !== "" && status !== "Success")) {
throw new Error(`BeeIMG 上传失败: ${response.content}`);
}
return fileUrl;
}
async function resolveSubjectReference(imageUrls, imagePaths) {
const resolvedUrls = parseStringList(imageUrls, "image_urls");
const resolvedPaths = parseStringList(imagePaths, "image_paths");
for (const url of resolvedUrls) {
if (!isProbablyUrl(url)) {
throw new Error(`image_urls 中包含无效链接: ${url}`);
}
}
for (const filePath of resolvedPaths) {
const uploadedUrl = await uploadImageToBeeimg(filePath);
resolvedUrls.push(uploadedUrl);
}
if (resolvedUrls.length === 0) {
return undefined;
}
return resolvedUrls.map(url => ({
type: "character",
image_file: url
}));
}
function normalizeBase64(base64) {
const raw = String(base64 || "").trim();
if (!raw) return raw;
const prefixIndex = raw.indexOf("base64,");
if (raw.startsWith("data:") && prefixIndex >= 0) {
return raw.substring(prefixIndex + "base64,".length).trim();
}
return raw;
}
function guessExtensionFromUrl(url, fallbackExtension) {
const match = String(url || "").match(/\.([a-z0-9]{2,5})(?:[?#].*)?$/i);
if (match && match[1]) return match[1].toLowerCase();
return fallbackExtension;
}
function parseMiniMaxError(parsed, fallbackMessage) {
const baseResp = isRecord(parsed) && isRecord(parsed.base_resp) ? parsed.base_resp : null;
if (!baseResp) return;
const statusCode = baseResp.status_code !== undefined ? Number(baseResp.status_code) : 0;
if (Number.isFinite(statusCode) && statusCode !== 0) {
const statusMsg = baseResp.status_msg ? String(baseResp.status_msg) : fallbackMessage;
throw new Error(`MiniMax 图片接口返回错误: ${statusMsg} (status_code=${statusCode})`);
}
}
async function callMiniMaxImageApi(params) {
const apiBaseUrl = getApiBaseUrl(params.api_base_url);
const endpoint = getImageEndpoint(apiBaseUrl);
const effectiveModel = resolveModel(params.model);
const responseFormat = normalizeResponseFormat(params.response_format);
const aspectRatio = normalizeAspectRatio(effectiveModel, params.aspect_ratio);
const dimensions = normalizeDimensions(effectiveModel, params.width, params.height, aspectRatio);
const imageCount = parsePositiveInteger(params.n, "n", { defaultValue: DEFAULT_IMAGE_COUNT, min: 1, max: 9 });
const promptOptimizer = parseBoolean(params.prompt_optimizer, "prompt_optimizer");
const aigcWatermark = parseBoolean(params.aigc_watermark, "aigc_watermark");
const seed = parseInteger(params.seed, "seed");
const subjectReference = await resolveSubjectReference(params.image_urls, params.image_paths);
const body: Record<string, unknown> = {
model: effectiveModel,
prompt: String(params.prompt || "").trim(),
response_format: responseFormat,
n: imageCount
};
if (aspectRatio) {
body.aspect_ratio = aspectRatio;
}
if (dimensions.width !== undefined && dimensions.height !== undefined) {
body.width = dimensions.width;
body.height = dimensions.height;
}
if (promptOptimizer !== undefined) {
body.prompt_optimizer = promptOptimizer;
}
if (aigcWatermark !== undefined) {
body.aigc_watermark = aigcWatermark;
}
if (seed !== undefined) {
body.seed = seed;
}
if (subjectReference) {
body.subject_reference = subjectReference;
}
const request = client
.newRequest()
.url(endpoint)
.method("POST")
.headers({
"accept": "application/json",
"content-type": "application/json",
"Authorization": `Bearer ${getApiKey()}`
})
.body(JSON.stringify(body), "json");
const response = await request.build().execute();
if (!response.isSuccessful()) {
throw new Error(`MiniMax 图片 API 调用失败: ${response.statusCode} - ${response.content}`);
}
let parsed;
try {
parsed = JSON.parse(response.content);
} catch (error) {
throw new Error(`解析 MiniMax 响应失败: ${getErrorMessage(error)}`);
}
parseMiniMaxError(parsed, "MiniMax 接口返回错误");
const data = isRecord(parsed) && isRecord(parsed.data) ? parsed.data : null;
if (!data) {
throw new Error("MiniMax 响应中未找到 data 对象。");
}
const metadata = isRecord(data.metadata) ? data.metadata : null;
const successCount = metadata && metadata.success_count !== undefined ? Number(metadata.success_count) : undefined;
const failedCount = metadata && metadata.failed_count !== undefined ? Number(metadata.failed_count) : undefined;
const requestId = isRecord(parsed) && parsed.id ? String(parsed.id) : "";
if (responseFormat === "base64") {
const imageBase64 = Array.isArray(data.image_base64)
? data.image_base64.map(item => String(item || "").trim()).filter(item => item.length > 0)
: [];
if (imageBase64.length === 0) {
throw new Error("MiniMax 响应中未找到 data.image_base64。");
}
return {
request_id: requestId,
effective_model: effectiveModel,
response_format: responseFormat,
image_base64: imageBase64,
image_urls: [],
success_count: Number.isFinite(successCount) ? successCount : imageBase64.length,
failed_count: Number.isFinite(failedCount) ? failedCount : 0,
reference_count: subjectReference ? subjectReference.length : 0
};
}
const imageUrls = Array.isArray(data.image_urls)
? data.image_urls.map(item => String(item || "").trim()).filter(item => item.length > 0)
: [];
if (imageUrls.length === 0) {
throw new Error("MiniMax 响应中未找到 data.image_urls。");
}
return {
request_id: requestId,
effective_model: effectiveModel,
response_format: responseFormat,
image_base64: [],
image_urls: imageUrls,
success_count: Number.isFinite(successCount) ? successCount : imageUrls.length,
failed_count: Number.isFinite(failedCount) ? failedCount : 0,
reference_count: subjectReference ? subjectReference.length : 0
};
}
async function draw_image(params) {
const prompt = String(params && params.prompt ? params.prompt : "").trim();
if (!prompt) {
throw new Error("参数 prompt 不能为空。");
}
await ensureDirectories();
const apiResult = await callMiniMaxImageApi({
prompt,
model: params.model,
aspect_ratio: params.aspect_ratio,
width: params.width,
height: params.height,
n: params.n,
response_format: params.response_format,
prompt_optimizer: params.prompt_optimizer,
aigc_watermark: params.aigc_watermark,
seed: params.seed,
image_urls: params.image_urls,
image_paths: params.image_paths,
api_base_url: params.api_base_url
});
const baseName = buildFileBaseName(prompt, params.file_name, "minimax_draw");
const files: Array<{
file_path: string;
file_uri: string;
markdown: string;
remote_image_url: string | null;
}> = [];
if (apiResult.response_format === "base64") {
for (let index = 0; index < apiResult.image_base64.length; index += 1) {
const suffix = apiResult.image_base64.length > 1 ? `_${index + 1}` : "";
const filePath = `${DRAWS_DIR}/${baseName}${suffix}.${DEFAULT_BASE64_EXTENSION}`;
const writeResult = await Tools.Files.writeBinary(filePath, normalizeBase64(apiResult.image_base64[index]));
if (!writeResult.successful) {
throw new Error(`保存图片失败: ${writeResult.details}`);
}
const fileUri = `file://${filePath}`;
files.push({
file_path: filePath,
file_uri: fileUri,
markdown: `![MiniMax 生成的图片${apiResult.image_base64.length > 1 ? ` ${index + 1}` : ""}](${fileUri})`,
remote_image_url: null
});
}
} else {
for (let index = 0; index < apiResult.image_urls.length; index += 1) {
const imageUrl = apiResult.image_urls[index];
const extension = guessExtensionFromUrl(imageUrl, "png");
const suffix = apiResult.image_urls.length > 1 ? `_${index + 1}` : "";
const filePath = `${DRAWS_DIR}/${baseName}${suffix}.${extension}`;
const downloadResult = await Tools.Files.download(imageUrl, filePath);
if (!downloadResult.successful) {
throw new Error(`下载图片失败: ${downloadResult.details}`);
}
const fileUri = `file://${filePath}`;
files.push({
file_path: filePath,
file_uri: fileUri,
markdown: `![MiniMax 生成的图片${apiResult.image_urls.length > 1 ? ` ${index + 1}` : ""}](${fileUri})`,
remote_image_url: imageUrl
});
}
}
const hintLines: string[] = [];
hintLines.push(`图片已生成并保存在本地 ${DRAWS_DIR}。`);
hintLines.push(`共生成 ${files.length} 张。`);
if (apiResult.reference_count > 0) {
hintLines.push(`本次使用了 ${apiResult.reference_count} 张参考图。`);
}
hintLines.push("");
hintLines.push("后续回答如果需要展示图片,请直接输出下面这些 Markdown:");
hintLines.push("");
for (const fileItem of files) {
hintLines.push(fileItem.markdown);
}
return {
prompt,
model: apiResult.effective_model,
request_id: apiResult.request_id || null,
response_format: apiResult.response_format,
success_count: apiResult.success_count,
failed_count: apiResult.failed_count,
reference_count: apiResult.reference_count,
file_path: files[0].file_path,
file_uri: files[0].file_uri,
markdown: files[0].markdown,
files,
hint: hintLines.join("\n")
};
}
async function draw_image_wrapper(params) {
try {
const result = await draw_image(params || {});
complete({
success: true,
message: "MiniMax 图片生成成功,已保存到本地。",
data: result
});
} catch (error) {
console.error("draw_image 执行失败:", error);
complete({
success: false,
message: `MiniMax 图片生成失败: ${getErrorMessage(error)}`,
error_stack: error && error.stack ? error.stack : undefined
});
}
}
return {
draw_image: draw_image_wrapper
};
})();
exports.draw_image = minimaxDraw.draw_image;