kingkont 0.20.26 → 0.20.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/providers.js +45 -26
- package/package.json +1 -1
package/lib/providers.js
CHANGED
|
@@ -322,23 +322,21 @@ async function startGeneration(args) {
|
|
|
322
322
|
const orAvailable = s.useOpenrouter && process.env.OPENROUTER_API_KEY;
|
|
323
323
|
const orImgModel = kind === 'image' && OPENROUTER_IMAGE_MODELS[orKey];
|
|
324
324
|
const orVidModel = kind === 'video' && OPENROUTER_VIDEO_MODELS[orKey];
|
|
325
|
-
// OpenRouter video API (/api/v1/videos)
|
|
326
|
-
// (см. _startGenerationViaOpenRouterVideo).
|
|
327
|
-
//
|
|
328
|
-
//
|
|
329
|
-
// reference_image_urls/imageInputs принимают
|
|
330
|
-
|
|
331
|
-
// генерация с потерей #2, чем ошибка «нет провайдера»).
|
|
332
|
-
const orVidMultiRef = orVidModel && kind === 'video' && (imageInputs?.length || 0) > 1;
|
|
325
|
+
// OpenRouter video API (/api/v1/videos) поддерживает до 2 refs через
|
|
326
|
+
// `frame_images` (first_frame + last_frame, см. _startGenerationViaOpenRouterVideo).
|
|
327
|
+
// Если refs > 2 — лишние теряем (frame_images семантически именно 2 кадра,
|
|
328
|
+
// а не «многоракурсные референсы»). Авто-роутинг multi-ref на Chatium/KIE
|
|
329
|
+
// — там reference_image_urls/imageInputs принимают массив любой длины.
|
|
330
|
+
const orVidExcessRefs = orVidModel && kind === 'video' && (imageInputs?.length || 0) > 2;
|
|
333
331
|
const _kieOkForOrKey = s.useKie && process.env.KIE_API_KEY && kind === 'video' && KIE_VIDEO_MODELS[orKey];
|
|
334
332
|
const _chatiumOkForOrKey = s.useChatium && s.chatium?.token && s.chatium?.base && kind === 'video' && CHATIUM_VIDEO_MODELS[orKey];
|
|
335
|
-
const orVidShouldFallback =
|
|
336
|
-
if (
|
|
333
|
+
const orVidShouldFallback = orVidExcessRefs && (_kieOkForOrKey || _chatiumOkForOrKey);
|
|
334
|
+
if (orVidExcessRefs) {
|
|
337
335
|
if (orVidShouldFallback) {
|
|
338
336
|
const target = _kieOkForOrKey ? 'KIE' : 'Chatium';
|
|
339
|
-
console.warn(`[providers] video "${orKey}" с ${imageInputs.length} refs → OpenRouter /
|
|
337
|
+
console.warn(`[providers] video "${orKey}" с ${imageInputs.length} refs → OpenRouter принимает 2 (first/last frame), роутим через ${target}`);
|
|
340
338
|
} else {
|
|
341
|
-
console.warn(`[providers] video "${orKey}" с ${imageInputs.length} refs, но Chatium/KIE
|
|
339
|
+
console.warn(`[providers] video "${orKey}" с ${imageInputs.length} refs, но Chatium/KIE недоступны → OR с первыми 2 (остальные ${imageInputs.length - 2} проигнорированы)`);
|
|
342
340
|
}
|
|
343
341
|
}
|
|
344
342
|
if (orAvailable && orImgModel) {
|
|
@@ -346,7 +344,7 @@ async function startGeneration(args) {
|
|
|
346
344
|
}
|
|
347
345
|
if (orAvailable && orVidModel && !orVidShouldFallback) {
|
|
348
346
|
return await _startGenerationViaOpenRouterVideo({
|
|
349
|
-
key: orKey, prompt, imageInputs, firstFrame, aspectRatio, resolution, duration,
|
|
347
|
+
key: orKey, prompt, imageInputs, firstFrame, lastFrame, aspectRatio, resolution, duration,
|
|
350
348
|
});
|
|
351
349
|
}
|
|
352
350
|
|
|
@@ -520,7 +518,7 @@ async function _startGenerationViaOpenRouter({ key, prompt, imageInputs, aspectR
|
|
|
520
518
|
// делает GET к polling_url (требует Bearer), при completed возвращает
|
|
521
519
|
// первый из unsigned_urls (тоже с auth — клиент идёт через /api/proxy,
|
|
522
520
|
// proxy-handler в server.js добавит Authorization для openrouter.ai/...).
|
|
523
|
-
async function _startGenerationViaOpenRouterVideo({ key, prompt, imageInputs, firstFrame, aspectRatio, resolution, duration }) {
|
|
521
|
+
async function _startGenerationViaOpenRouterVideo({ key, prompt, imageInputs, firstFrame, lastFrame, aspectRatio, resolution, duration }) {
|
|
524
522
|
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
525
523
|
const model = OPENROUTER_VIDEO_MODELS[key];
|
|
526
524
|
if (!model) throw new Error(`OpenRouter не поддерживает video-модель "${key}"`);
|
|
@@ -528,21 +526,42 @@ async function _startGenerationViaOpenRouterVideo({ key, prompt, imageInputs, fi
|
|
|
528
526
|
if (duration) body.duration = +duration;
|
|
529
527
|
if (aspectRatio) body.aspect_ratio = aspectRatio;
|
|
530
528
|
if (resolution) body.resolution = resolution;
|
|
531
|
-
// image-to-video:
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
//
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
|
|
538
|
-
|
|
529
|
+
// image-to-video: правильная схема OR `/api/v1/videos` — массив
|
|
530
|
+
// `frame_images` с объектами `{type:"image_url", image_url:{url}, frame_type}`.
|
|
531
|
+
// Поддерживаемые frame_type для seedance/kling: "first_frame", "last_frame"
|
|
532
|
+
// (см. /api/v1/videos/models → supported_frame_images).
|
|
533
|
+
// Раньше слали bare `image_input`/`image_url` строкой — OR молча игнорировал,
|
|
534
|
+
// и генерация шла как text-to-video. Юзер: «1 реф — он не использовался».
|
|
535
|
+
// Проверено эмпирически: сравнение двух запросов с одинаковым промптом,
|
|
536
|
+
// один с `frame_images`, другой с bare-полем → результаты ВИЗУАЛЬНО
|
|
537
|
+
// различаются (правильный шейп даёт i2v из заданной картинки).
|
|
538
|
+
const frameImages = [];
|
|
539
|
+
const start = firstFrame || (Array.isArray(imageInputs) && imageInputs[0]) || null;
|
|
540
|
+
const end = lastFrame || (Array.isArray(imageInputs) && imageInputs[1]) || null;
|
|
541
|
+
if (start) frameImages.push({
|
|
542
|
+
type: 'image_url', image_url: { url: start }, frame_type: 'first_frame',
|
|
543
|
+
});
|
|
544
|
+
if (end) frameImages.push({
|
|
545
|
+
type: 'image_url', image_url: { url: end }, frame_type: 'last_frame',
|
|
546
|
+
});
|
|
547
|
+
if (frameImages.length) body.frame_images = frameImages;
|
|
548
|
+
// refs > 2 для OR video не поддерживаются — лишние теряем (предупреждение
|
|
549
|
+
// выше в startGeneration уже отрабатывает для multi-ref → Chatium routing,
|
|
550
|
+
// но если попали сюда — просто игнорим #3+).
|
|
551
|
+
if (Array.isArray(imageInputs) && imageInputs.length > 2) {
|
|
552
|
+
console.warn(`[providers] OR video поддерживает только first/last frame (2 refs), у тебя ${imageInputs.length} — лишние #${frameImages.length+1}+ игнорированы`);
|
|
553
|
+
}
|
|
539
554
|
logCall('POST', 'OpenRouter', 'https://openrouter.ai/api/v1/videos',
|
|
540
|
-
`model=${model} dur=${duration || '-'}s asp=${aspectRatio || '-'} res=${resolution || '-'} i2v=${
|
|
555
|
+
`model=${model} dur=${duration || '-'}s asp=${aspectRatio || '-'} res=${resolution || '-'} i2v=${frameImages.length ? `${frameImages.length}-frame` : 'no'}`);
|
|
541
556
|
// Полный body-dump в лог — для верификации какие поля принял OpenRouter
|
|
542
|
-
// (особенно `
|
|
543
|
-
//
|
|
557
|
+
// (особенно `frame_images` для i2v — раньше bare image_url/image_input
|
|
558
|
+
// молча игнорировались, см. v0.20.27).
|
|
544
559
|
const bodyForLog = { ...body };
|
|
545
|
-
if (bodyForLog.
|
|
560
|
+
if (bodyForLog.frame_images) {
|
|
561
|
+
bodyForLog.frame_images = bodyForLog.frame_images.map(fi => ({
|
|
562
|
+
...fi, image_url: { url: String(fi.image_url?.url || '').slice(0, 120) + '…' },
|
|
563
|
+
}));
|
|
564
|
+
}
|
|
546
565
|
console.log(`[providers] OpenRouter video body: ${JSON.stringify(bodyForLog)}`);
|
|
547
566
|
const r = await fetch('https://openrouter.ai/api/v1/videos', {
|
|
548
567
|
method: 'POST',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kingkont",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.28",
|
|
4
4
|
"description": "KingKont \u00b7 Chatium \u2014 \u043d\u043e\u0434-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0446\u0435\u043d \u0441 AI-\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438/\u0432\u0438\u0434\u0435\u043e/\u0433\u043e\u043b\u043e\u0441/SFX/\u043c\u0443\u0437\u044b\u043a\u0430/\u0442\u0435\u043a\u0441\u0442)",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|