forked from admin/zeropost-engine
eede50bee7
config/index.js: добавили ROUTERAI_BASE_URL, ROUTERAI_API_KEY в список keys который загружается из app_settings через reloadAi() Без этого ключ был NULL и все генерации падали в local SVG fallback
84 lines
3.9 KiB
JavaScript
84 lines
3.9 KiB
JavaScript
require('dotenv').config();
|
||
|
||
// settings подгружаем лениво, чтобы избежать циклической зависимости
|
||
// (settings → config/db → config/index). require здесь синхронный, но settings.getMany async.
|
||
let _settingsSvc = null;
|
||
function settingsSvc() {
|
||
if (!_settingsSvc) _settingsSvc = require('../services/settings');
|
||
return _settingsSvc;
|
||
}
|
||
|
||
const config = {
|
||
port: parseInt(process.env.ZEROPOST_PORT || 3030),
|
||
|
||
// AI gateway — значения мутируются reloadAi() из app_settings.
|
||
// Дефолты ниже — последний fallback, если БД и .env пустые.
|
||
ai: {
|
||
baseUrl: process.env.AI_BASE_URL || 'https://aiprimetech.io/v1',
|
||
apiKey: process.env.AI_API_KEY || null,
|
||
imageApiKey: process.env.AI_IMAGE_API_KEY || process.env.AI_API_KEY || null,
|
||
imageBaseUrl: process.env.AI_IMAGE_BASE_URL || 'https://api.aiguoguo199.com/v1',
|
||
imageModel: process.env.AI_MODEL_IMAGE || 'gpt-image-1-mini',
|
||
imageModelViaResponses: process.env.AI_MODEL_IMAGE_VIA_RESPONSES || 'gpt-5.5',
|
||
models: {
|
||
post: process.env.AI_MODEL_POST || 'claude-haiku-4-5-20251001',
|
||
article: process.env.AI_MODEL_ARTICLE || 'claude-sonnet-4-6',
|
||
topics: process.env.AI_MODEL_TOPICS || 'claude-haiku-4-5-20251001',
|
||
image: process.env.AI_MODEL_IMAGE || 'gpt-image-1-mini',
|
||
},
|
||
},
|
||
|
||
db: {
|
||
host: process.env.DB_HOST || 'localhost',
|
||
port: process.env.DB_PORT || 5432,
|
||
database: process.env.DB_NAME || 'zeropost',
|
||
user: process.env.DB_USER || 'postgres',
|
||
password: process.env.DB_PASS || 'postgres',
|
||
},
|
||
redis: {
|
||
host: process.env.REDIS_HOST || 'localhost',
|
||
port: process.env.REDIS_PORT || 6379,
|
||
},
|
||
internalSecret: process.env.INTERNAL_SECRET || 'dev-secret-change-in-prod',
|
||
};
|
||
|
||
/**
|
||
* Перегружает блок ai из app_settings.
|
||
* Приоритет: app_settings.value → process.env[НОВОЕ_ИМЯ] → process.env[СТАРОЕ_ИМЯ] → дефолт.
|
||
* Старое имя ENV нужно для безопасной миграции — если БД пуста, .env держит прод на ногах.
|
||
* Мутирует config.ai в месте, чтобы все require'нувшие config продолжали видеть актуальные значения.
|
||
*/
|
||
async function reloadAi() {
|
||
const keys = [
|
||
'AI_TEXT_BASE_URL', 'AI_TEXT_API_KEY',
|
||
'AI_TEXT_MODEL_POST', 'AI_TEXT_MODEL_ARTICLE', 'AI_TEXT_MODEL_TOPICS',
|
||
'ROUTERAI_BASE_URL', 'ROUTERAI_API_KEY',
|
||
];
|
||
let s = {};
|
||
try {
|
||
s = await settingsSvc().getMany(keys);
|
||
} catch (err) {
|
||
console.warn('[config.reloadAi] DB unavailable, using ENV fallback:', err.message);
|
||
}
|
||
const pick = (dbKey, envOld, def) =>
|
||
(s[dbKey] && s[dbKey].trim()) || process.env[dbKey] || process.env[envOld] || def;
|
||
|
||
// Текст — aiprimetech.io
|
||
config.ai.baseUrl = pick('AI_TEXT_BASE_URL', 'AI_BASE_URL', 'https://aiprimetech.io/v1');
|
||
config.ai.apiKey = pick('AI_TEXT_API_KEY', 'AI_API_KEY', null);
|
||
config.ai.models.post = pick('AI_TEXT_MODEL_POST', 'AI_MODEL_POST', 'claude-haiku-4-5-20251001');
|
||
config.ai.models.article = pick('AI_TEXT_MODEL_ARTICLE', 'AI_MODEL_ARTICLE', 'claude-sonnet-4-6');
|
||
config.ai.models.topics = pick('AI_TEXT_MODEL_TOPICS', 'AI_MODEL_TOPICS', 'claude-haiku-4-5-20251001');
|
||
|
||
// Картинки — routerai.ru (только gpt-5-image-mini, /responses endpoint)
|
||
// Реальная цена: ₽2.72/картинка (4175 image tokens × ₽0.000747 + input - output discount)
|
||
config.ai.routeraiBaseUrl = (s['ROUTERAI_BASE_URL'] || 'https://routerai.ru/api/v1').trim();
|
||
config.ai.routeraiApiKey = (s['ROUTERAI_API_KEY'] || '').trim() || null;
|
||
config.ai.routeraiModel = 'openai/gpt-5-image-mini'; // единственная модель, quality всегда high
|
||
|
||
return config.ai;
|
||
}
|
||
|
||
config.reloadAi = reloadAi;
|
||
module.exports = config;
|