init: image-generator with MiniMax image-01 support

This commit is contained in:
zwbcc
2026-03-25 23:49:47 +08:00
commit 2837bc1a85
5 changed files with 1020 additions and 0 deletions

115
app.js Normal file
View File

@@ -0,0 +1,115 @@
'use strict';
// ============================================================
// Config
// ============================================================
const express = require('express');
const fetch = require('node-fetch');
const path = require('path');
const fs = require('fs');
const PORT = 8195;
const HOST = '0.0.0.0';
// Config file stored alongside app.js
const CONFIG_FILE = path.join(__dirname, 'config.json');
function loadConfig() {
try {
return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
} catch {
return { apiKey: '', baseUrl: 'https://api.minimax.io' };
}
}
function saveConfig(cfg) {
fs.writeFileSync(CONFIG_FILE, JSON.stringify(cfg, null, 2));
}
// ============================================================
// App
// ============================================================
const app = express();
app.use(express.json());
app.use(express.static(__dirname));
// --- Settings ---
app.get('/api/config', (req, res) => {
const cfg = loadConfig();
res.json({
hasApiKey: !!cfg.apiKey,
baseUrl: cfg.baseUrl || 'https://api.minimax.io',
});
});
app.post('/api/config', (req, res) => {
const { apiKey, baseUrl } = req.body;
if (typeof apiKey !== 'string' || typeof baseUrl !== 'string') {
return res.status(400).json({ error: 'Invalid fields' });
}
const cfg = { apiKey: apiKey.trim(), baseUrl: baseUrl.trim() || 'https://api.minimax.io' };
saveConfig(cfg);
res.json({ ok: true });
});
// --- Image generation ---
app.post('/api/generate', async (req, res) => {
const { prompt, aspect_ratio, model } = req.body;
if (!prompt || typeof prompt !== 'string' || !prompt.trim()) {
return res.status(400).json({ error: 'prompt is required' });
}
const cfg = loadConfig();
if (!cfg.apiKey) {
return res.status(400).json({ error: 'API key not configured. Please set your MiniMax API key in settings.' });
}
const baseUrl = cfg.baseUrl || 'https://api.minimax.io';
const endpoint = `${baseUrl}/v1/image_generation`;
const payload = {
model: model || 'image-01',
prompt: prompt.trim(),
aspect_ratio: aspect_ratio || '1:1',
response_format: 'base64',
};
try {
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Authorization': `Bearer ${cfg.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const data = await response.json();
if (!response.ok) {
const msg = data.error?.message || data.error || `HTTP ${response.status}`;
return res.status(response.status).json({ error: msg });
}
// Return base64 images
const images = data.data?.image_base64 || [];
res.json({ images });
} catch (err) {
console.error('[generate] error:', err.message);
res.status(500).json({ error: 'Failed to reach MiniMax API: ' + err.message });
}
});
// --- Serve index.html at root ---
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(PORT, HOST, () => {
console.log(`Image Generator running at http://${HOST === '0.0.0.0' ? '10.0.10.110' : HOST}:${PORT}`);
});