kingkont 0.20.41 → 0.20.43
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 +7 -4
- package/package.json +1 -1
- package/renderer/board.js +17 -22
- package/renderer/genLogger.js +6 -2
- package/renderer/media.js +7 -1
- package/renderer/state.js +29 -5
package/index.html
CHANGED
|
@@ -399,6 +399,13 @@
|
|
|
399
399
|
<div class="modal hidden" id="genModal">
|
|
400
400
|
<div class="modal-card">
|
|
401
401
|
<h3 id="genTitle">Сгенерировать ноду</h3>
|
|
402
|
+
<!-- Промпт первым — юзер: «в модалке любой генерации поле промпта
|
|
403
|
+
перенеси на самый верх». Сначала юзер пишет что нужно, потом
|
|
404
|
+
настраивает модель / aspect / refs. -->
|
|
405
|
+
<label><span style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis; display:block;">Описание · <span style="color:#aae06a; font-family:ui-monospace,monospace; text-transform:none;">@имя</span> для ссылки на ноду</span>
|
|
406
|
+
<textarea id="genPrompt" placeholder="Опиши, что должно быть. Печатай @ чтобы вставить ссылку на ноду..."></textarea>
|
|
407
|
+
<div id="mentionPopup" class="mention-popup hidden"></div>
|
|
408
|
+
</label>
|
|
402
409
|
<div class="field-row" style="display:none;">Тип
|
|
403
410
|
<div class="seg-control">
|
|
404
411
|
<button class="seg active" data-kind="image" type="button">Картинка</button>
|
|
@@ -518,10 +525,6 @@
|
|
|
518
525
|
</label>
|
|
519
526
|
<!-- Дефолтные промпты сцены (стек чекбоксов; рендерится динамически) -->
|
|
520
527
|
<div id="genDefaultPromptsRow" style="display:none; margin-bottom:8px; flex-direction:column; gap:6px;"></div>
|
|
521
|
-
<label><span style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis; display:block;">Описание · <span style="color:#aae06a; font-family:ui-monospace,monospace; text-transform:none;">@имя</span> для ссылки на ноду</span>
|
|
522
|
-
<textarea id="genPrompt" placeholder="Опиши, что должно быть. Печатай @ чтобы вставить ссылку на ноду..."></textarea>
|
|
523
|
-
<div id="mentionPopup" class="mention-popup hidden"></div>
|
|
524
|
-
</label>
|
|
525
528
|
<div class="modal-actions">
|
|
526
529
|
<span id="genStatus" class="status"></span>
|
|
527
530
|
<span class="spacer"></span>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kingkont",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.43",
|
|
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": {
|
package/renderer/board.js
CHANGED
|
@@ -4125,34 +4125,29 @@ function showNodeContextMenu(node, clientX, clientY) {
|
|
|
4125
4125
|
add('⚙ Параметры', () => showNodeSettings(node));
|
|
4126
4126
|
if (node.status === 'generating') {
|
|
4127
4127
|
add('⏹ Остановить', () => stopJob(node.id));
|
|
4128
|
-
//
|
|
4129
|
-
//
|
|
4130
|
-
//
|
|
4131
|
-
//
|
|
4132
|
-
//
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4128
|
+
// «✎ Изменить и запустить» открывает модалку даже когда генерация
|
|
4129
|
+
// идёт. Юзер: «когда идёт генерация ноды — всё-равно нужно уметь
|
|
4130
|
+
// открыть через ПКМ возможность перезапуска генерации с новыми
|
|
4131
|
+
// параметрами (пусть 2 параллельно идут)».
|
|
4132
|
+
// Не стопим текущий job: submit в модалке overwrite'нет
|
|
4133
|
+
// state.jobs entry для этого node.id, старый pollJob выйдет по
|
|
4134
|
+
// guard'у `state.jobs.get(node.id) !== job` — мы получим один
|
|
4135
|
+
// активный job (новый). На сервере таски разные taskId — оба
|
|
4136
|
+
// отработают, второй последним перезапишет node.file.
|
|
4137
|
+
add('✎ Изменить и запустить', () => regenerateNode(node));
|
|
4138
4138
|
}
|
|
4139
4139
|
else if (node.status === 'draft') {
|
|
4140
|
-
//
|
|
4141
|
-
//
|
|
4142
|
-
//
|
|
4143
|
-
// параметры + incoming-edge рефы).
|
|
4144
|
-
// ✎ Изменить и запустить — открыть modal для правки промпта/
|
|
4145
|
-
// модели/настроек, потом запустить.
|
|
4140
|
+
// ▶ Запустить — direct-run без модалки (сохранённые параметры +
|
|
4141
|
+
// incoming-edge рефы).
|
|
4142
|
+
// ✎ Изменить и запустить — открыть modal, поправить, запустить.
|
|
4146
4143
|
add('▶ Запустить генерацию', () => runNodeJobDirectly(node));
|
|
4147
4144
|
add('✎ Изменить и запустить', () => regenerateNode(node));
|
|
4148
4145
|
}
|
|
4149
4146
|
else if (node.generated) {
|
|
4150
|
-
// Готовая нода:
|
|
4151
|
-
//
|
|
4152
|
-
//
|
|
4153
|
-
|
|
4154
|
-
add('↻ Перегенерировать', () => runNodeJobDirectly(node));
|
|
4155
|
-
add('↻ Перегенерировать (правка)', () => regenerateNode(node));
|
|
4147
|
+
// Готовая нода: только модал-вариант. Юзер: «убери из ПКМ ноды
|
|
4148
|
+
// 'перегенерировать'». Direct-run (без модалки) убран — он
|
|
4149
|
+
// запускался по case'у и был неотличим от модалки в UI.
|
|
4150
|
+
add('✎ Изменить и запустить', () => regenerateNode(node));
|
|
4156
4151
|
}
|
|
4157
4152
|
if (node.type === 'image' || node.type === 'video' || node.type === 'audio') {
|
|
4158
4153
|
add('➕ В таймлайн', () => addToTimeline(node));
|
package/renderer/genLogger.js
CHANGED
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
// автоматически вставляется из state и window.appVersion/cloudFs.
|
|
18
18
|
|
|
19
19
|
(function () {
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// Юзер: «если происходят проблемы при загрузке референса — я тоже хочу
|
|
21
|
+
// знать из логов, причём ещё до того как генерация закончена». Снизили
|
|
22
|
+
// 3s → 1s, чтобы любая info-строка через секунду максимум была на сервере.
|
|
23
|
+
// event/error и сейчас flush'ятся немедленно (см. ниже).
|
|
24
|
+
const FLUSH_INTERVAL_MS = 1000;
|
|
25
|
+
const MAX_BUFFER = 50; // если буфер набил — flush сразу
|
|
22
26
|
const MAX_PER_REQUEST = 100; // server ограничивает до 100/batch
|
|
23
27
|
|
|
24
28
|
const PLATFORM = window.cloudFs ? 'electron' : 'web';
|
package/renderer/media.js
CHANGED
|
@@ -682,7 +682,13 @@ function _shortImageModelFromGen(g) {
|
|
|
682
682
|
}
|
|
683
683
|
|
|
684
684
|
async function regenerateNode(node) {
|
|
685
|
-
if (
|
|
685
|
+
// Раньше: `if (status === 'generating') return` — блокировало открытие
|
|
686
|
+
// модалки во время активной генерации. Юзер: «когда идёт генерация —
|
|
687
|
+
// всё-равно нужно уметь открыть через ПКМ возможность перезапуска
|
|
688
|
+
// с новыми параметрами». Снято: модалка открывается даже на generating.
|
|
689
|
+
// При submit'е новый regenerateInto через mutateNode/scheduleSave
|
|
690
|
+
// перезапишет node state, старый job выйдет по guard'у в pollJob
|
|
691
|
+
// (state.jobs.get(node.id) !== job).
|
|
686
692
|
const g = node.generated || {};
|
|
687
693
|
// SFX / Music — отдельный flow, чтобы не путать с TTS-голосом.
|
|
688
694
|
if (g.subKind === 'sfx') {
|
package/renderer/state.js
CHANGED
|
@@ -690,10 +690,19 @@ function logJob(nodeId, msg) {
|
|
|
690
690
|
// Юзер: «все логи генераций должны писаться на сервер с указанием что
|
|
691
691
|
// делалось, в какой сцене — чтобы я мог считать когда говорю
|
|
692
692
|
// 'у пользователя email проблема с последней генерацией'».
|
|
693
|
+
//
|
|
694
|
+
// Уровень определяется по содержимому строки — error/event flush'атся
|
|
695
|
+
// немедленно, info ждёт обычный 1s-батч.
|
|
696
|
+
// Юзер: «если проблемы при загрузке референса — хочу знать ещё до того
|
|
697
|
+
// как генерация закончена; на любом этапе если не случилась генерация
|
|
698
|
+
// или случилась не та что ожидали — нужно знать». Поэтому ключевые
|
|
699
|
+
// milestones (upload start/done, request body, taskId, poll done) идут
|
|
700
|
+
// как event → flush сразу.
|
|
693
701
|
try {
|
|
694
|
-
const lvl =
|
|
695
|
-
|
|
696
|
-
|
|
702
|
+
const lvl =
|
|
703
|
+
/error|failed|✗\s|ошиб|reject|invalid/i.test(msg) ? 'error' :
|
|
704
|
+
/gen start|gen ERROR|✓|done\s|✓ ok|→ POST|POST \/api\/|via\s+\w+\s+HTTP|taskId=|done →|↳ ok|↳ FAILED|upload (ref|summary)|списано|cost=|i2v=|frame_images|imageInputs|provider error|video params|gen params/i.test(msg) ? 'event' :
|
|
705
|
+
'info';
|
|
697
706
|
window.kkGenLogger?.append?.({ nodeId, msg, level: lvl });
|
|
698
707
|
} catch {}
|
|
699
708
|
}
|
|
@@ -743,12 +752,27 @@ async function plannedProvider(kind) {
|
|
|
743
752
|
return '?';
|
|
744
753
|
}
|
|
745
754
|
}
|
|
746
|
-
// Безопасная сериализация для логов: обрезает длинные строки и убирает blob/handle
|
|
755
|
+
// Безопасная сериализация для логов: обрезает длинные строки и убирает blob/handle.
|
|
756
|
+
// Юзер: «не понимаю, использует ли openai-image-2 референсы; нужно из логов
|
|
757
|
+
// оценить» — поэтому imageInputs/videoInputs/refs/url НЕ обрезаем (URL'ы
|
|
758
|
+
// иначе превращались в '...' и нельзя было сверить hash файла). Остальные
|
|
759
|
+
// длинные строки (prompt > 500ch) урезаем как раньше.
|
|
747
760
|
function logSafe(obj) {
|
|
748
761
|
try {
|
|
762
|
+
const URL_FIELDS = new Set(['url', 'image_url', 'image_input', 'imageInputs', 'videoInputs',
|
|
763
|
+
'firstFrame', 'lastFrame', 'frame_images', 'refs',
|
|
764
|
+
'reference_image_urls', 'reference_video_urls', 'taskId']);
|
|
749
765
|
return JSON.stringify(obj, (k, v) => {
|
|
750
766
|
if (k === 'boardHandle') return v ? `<DirectoryHandle ${v.name || ''}>` : null;
|
|
751
|
-
|
|
767
|
+
// URL-поля сохраняем целиком — это часто диагностический материал.
|
|
768
|
+
if (URL_FIELDS.has(k)) return v;
|
|
769
|
+
// Внутри array URL_FIELDS (imageInputs[0], imageInputs[1]) ключи — индексы,
|
|
770
|
+
// там logSafe приходит как k='0','1',... → URL_FIELDS не сработает.
|
|
771
|
+
// Поэтому ниже специально не режем URL-подобные строки.
|
|
772
|
+
if (typeof v === 'string') {
|
|
773
|
+
if (/^https?:\/\//.test(v)) return v; // URL целиком
|
|
774
|
+
if (v.length > 500) return v.slice(0, 500) + `…(+${v.length - 500} chars)`;
|
|
775
|
+
}
|
|
752
776
|
return v;
|
|
753
777
|
});
|
|
754
778
|
} catch (e) { return String(obj); }
|