kingkont 0.19.3 → 0.20.1

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/index.html CHANGED
@@ -389,9 +389,11 @@
389
389
  </div>
390
390
  </div>
391
391
  <div class="field-row" id="imageModelRow">Модель для картинки
392
- <div class="seg-control">
392
+ <div class="seg-control" style="flex-wrap:wrap;">
393
393
  <button class="seg active" data-img-model="nano-banana-2" type="button" title="Высокое качество, медленно">Nano Banana 2</button>
394
394
  <button class="seg" data-img-model="nano-banana-pro" type="button" title="Pro-версия nano-banana, выше качество">Nano Banana Pro</button>
395
+ <button class="seg" data-img-model="gpt-image-2" type="button" title="OpenAI GPT Image 2 — text-to-image и edit">GPT Image 2</button>
396
+ <button class="seg" data-img-model="gpt-image-1.5" type="button" title="OpenAI GPT Image 1.5 — старее, дешевле">GPT Image 1.5</button>
395
397
  <button class="seg" data-img-model="grok" type="button">Grok</button>
396
398
  <button class="seg" data-img-model="seedream" type="button">Seedream 4.5</button>
397
399
  <button class="seg" data-img-model="seedream-5-lite" type="button">Seedream 5 Lite</button>
package/lib/providers.js CHANGED
@@ -70,6 +70,11 @@ const KIE_IMAGE_MODELS = {
70
70
  'seedream-5-lite': 'seedream/5-lite-text-to-image',
71
71
  'flux-schnell': 'flux/schnell',
72
72
  'sdxl-lightning': 'sdxl/lightning',
73
+ // OpenAI gpt-image (через KIE — другие провайдеры не выкладывают).
74
+ // KIE автоматически переключает text-to-image vs image-to-image по
75
+ // наличию image_input — оба ходят через один и тот же jobs/createTask.
76
+ 'gpt-image-2': 'gpt-image-2-text-to-image',
77
+ 'gpt-image-1.5': 'gpt-image/1.5-text-to-image',
73
78
  };
74
79
  const KIE_VIDEO_MODELS = {
75
80
  'seedance-2': 'bytedance/seedance-2',
@@ -81,6 +86,11 @@ const CHATIUM_IMAGE_MODELS = {
81
86
  'grok': 'grok-imagine/text-to-image',
82
87
  'grok-i2i': 'grok-imagine/image-to-image',
83
88
  'seedream-5-lite': 'bytedance/seedream-5-lite',
89
+ // OpenAI gpt-image-2 — Chatium proxy поддерживает (проверено через
90
+ // probe). image-to-image вариант под отдельным slug, переключаем
91
+ // в startGeneration при наличии imageInputs.
92
+ // (gpt-image/1.5 НЕ доступен через Chatium — только KIE.)
93
+ 'gpt-image-2': 'gpt-image-2-text-to-image',
84
94
  };
85
95
  const CHATIUM_VIDEO_MODELS = {
86
96
  'seedance-2': 'bytedance/seedance-2',
@@ -106,6 +116,20 @@ function resolveModel(map, key, fallback) {
106
116
  return map[key] || (Object.values(map).includes(key) ? key : null);
107
117
  }
108
118
 
119
+ // gpt-image поддерживает только 3 размера: квадрат, портрет, ландшафт.
120
+ // Маппим наши aspectRatio'ы в ближайший подходящий size string.
121
+ function _gptImageAspectToSize(aspectRatio) {
122
+ if (!aspectRatio) return '1024x1024';
123
+ // Парсим "W:H".
124
+ const m = String(aspectRatio).match(/^(\d+):(\d+)$/);
125
+ if (!m) return '1024x1024';
126
+ const w = +m[1], h = +m[2];
127
+ const ratio = w / h;
128
+ if (ratio > 1.15) return '1536x1024'; // ландшафт (16:9, 3:2, 4:3)
129
+ if (ratio < 0.87) return '1024x1536'; // портрет (9:16, 2:3, 3:4)
130
+ return '1024x1024'; // квадрат (1:1)
131
+ }
132
+
109
133
  // =============================================================================
110
134
  // Chatium HTTP helpers (text/audio/image/video дёргают одни и те же).
111
135
  // =============================================================================
@@ -285,7 +309,15 @@ async function startGeneration(args) {
285
309
  const kieAvailable = s.useKie && process.env.KIE_API_KEY;
286
310
  const kieSupportsModel = !!kieMap[kieKey];
287
311
 
288
- if (kieAvailable && kieSupportsModel) {
312
+ // gpt-image-2 — приоритет Chatium (биллинг через kingkont credits,
313
+ // юзеру одна точка оплаты). KIE — fallback если Chatium недоступен
314
+ // или не поддерживает модель (например gpt-image-1.5).
315
+ const chatiumAvailable = s.useChatium && s.chatium?.token && s.chatium?.base;
316
+ const chatiumMap = kind === 'video' ? CHATIUM_VIDEO_MODELS : CHATIUM_IMAGE_MODELS;
317
+ const isGptImage = kind === 'image' && (kieKey === 'gpt-image-2' || kieKey === 'gpt-image-1.5');
318
+ if (isGptImage && chatiumAvailable && chatiumMap[kieKey]) {
319
+ // → Chatium-путь ниже (skip KIE).
320
+ } else if (kieAvailable && kieSupportsModel) {
289
321
  return await _startGenerationViaKie({ kind, prompt, key: kieKey, imageInputs, videoInputs, aspectRatio, resolution, duration, quality });
290
322
  }
291
323
 
@@ -305,8 +337,14 @@ async function startGeneration(args) {
305
337
  body = { prompt, model: fullModel, imageInputs, videoInputs, firstFrame, lastFrame, aspectRatio, resolution, duration };
306
338
  } else {
307
339
  const isSeedream = fullModel.includes('seedream');
340
+ const isGptImage = fullModel.startsWith('gpt-image');
341
+ // gpt-image-2 — auto-switch на image-to-image вариант если есть refs.
342
+ let actualModel = fullModel;
343
+ if (isGptImage && imageInputs?.length) {
344
+ actualModel = 'gpt-image-2-image-to-image';
345
+ }
308
346
  body = {
309
- prompt, model: fullModel, aspectRatio, resolution,
347
+ prompt, model: actualModel, aspectRatio, resolution,
310
348
  outputFormat: isSeedream ? 'jpeg' : 'jpg',
311
349
  };
312
350
  if (quality) body.quality = quality; // 'low' | 'medium' | 'high' — модель сама решит как мапить
@@ -454,6 +492,19 @@ async function _startGenerationViaKie({ kind, prompt, key, imageInputs, videoInp
454
492
  if (aspectRatio) input.aspect_ratio = aspectRatio;
455
493
  input.output_format = 'jpg';
456
494
  // flux/sdxl быстрые, quality для них N/A — пропускаем.
495
+ } else if (key === 'gpt-image-2' || key === 'gpt-image-1.5') {
496
+ // OpenAI gpt-image-2 / 1.5 через KIE. Если есть imageInputs —
497
+ // переключаемся на image-to-image вариант slug'а (KIE использует
498
+ // отдельные модели для t2i vs i2i).
499
+ if (imageInputs?.length) {
500
+ // gpt-image-2-image-to-image — same input.image_input format,
501
+ // нужно сменить fullModel ниже.
502
+ }
503
+ if (aspectRatio) input.size = _gptImageAspectToSize(aspectRatio);
504
+ if (imageInputs?.length) input.image_input = imageInputs;
505
+ // quality: 'low' | 'medium' | 'high' — gpt-image поддерживает.
506
+ if (quality) input.quality = quality;
507
+ input.output_format = 'jpg';
457
508
  }
458
509
  } else {
459
510
  if (imageInputs?.length) input.reference_image_urls = imageInputs;
@@ -463,10 +514,18 @@ async function _startGenerationViaKie({ kind, prompt, key, imageInputs, videoInp
463
514
  if (duration) input.duration = +duration;
464
515
  }
465
516
 
466
- logCall('POST', 'KIE', `${KIE_BASE}/api/v1/jobs/createTask`, `model=${fullModel} kind=${kind}`);
517
+ // gpt-image-* переключаем slug на image-to-image variant если есть refs.
518
+ let actualModel = fullModel;
519
+ if ((key === 'gpt-image-2' || key === 'gpt-image-1.5') && imageInputs?.length) {
520
+ actualModel = key === 'gpt-image-2'
521
+ ? 'gpt-image-2-image-to-image'
522
+ : 'gpt-image/1.5-image-to-image';
523
+ }
524
+
525
+ logCall('POST', 'KIE', `${KIE_BASE}/api/v1/jobs/createTask`, `model=${actualModel} kind=${kind}`);
467
526
  const data = await kieFetch('/api/v1/jobs/createTask', {
468
527
  method: 'POST',
469
- body: JSON.stringify({ model: fullModel, input }),
528
+ body: JSON.stringify({ model: actualModel, input }),
470
529
  });
471
530
  // Защита: KIE иногда возвращает 200 с code=200 но без data.taskId (например
472
531
  // когда модель не поддерживает текущий input — null aspect_ratio для grok,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.19.3",
3
+ "version": "0.20.1",
4
4
  "description": "KingKont · Chatium — нод-редактор сцен с AI-генерацией (картинки/видео/голос/SFX/музыка/текст)",
5
5
  "main": "main.js",
6
6
  "bin": {
@@ -1687,6 +1687,10 @@ $('genSubmit').addEventListener('click', async () => {
1687
1687
  'seedream-5-lite': 'seedream/5-lite-text-to-image',
1688
1688
  'nano-banana-2': 'nano-banana-2',
1689
1689
  'nano-banana-pro': 'nano-banana-pro',
1690
+ 'gpt-image-2': 'gpt-image-2-text-to-image',
1691
+ 'gpt-image-1.5': 'gpt-image/1.5-text-to-image',
1692
+ 'flux-schnell': 'flux/schnell',
1693
+ 'sdxl-lightning': 'sdxl/lightning',
1690
1694
  }[state.imageModel] || 'nano-banana-2')
1691
1695
  : ({
1692
1696
  'seedance-2': 'bytedance/seedance-2',