kingkont 0.7.41 → 0.7.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/bin/kingkont.js CHANGED
@@ -106,7 +106,12 @@ if (cmd && NODE_COMMANDS[cmd]) {
106
106
  process.env.PORT = String(port);
107
107
  const targetPath = args[1] && !args[1].startsWith('--') ? path.resolve(args[1]) : null;
108
108
  const { start } = require(path.join(root, 'server.js'));
109
- start(port).then(actualPort => {
109
+ // Live-чтение settings.json на каждый запрос — так же как в Electron-режиме
110
+ // (main.js). Без этого use*-флаги и chatium.token не доходят до server.js,
111
+ // и провайдеры (chatium / openrouter / kie / elevenlabs) висят выключенными,
112
+ // даже если юзер залогинен через UI приложения.
113
+ const startOpts = { getSettings: () => settingsLib.loadSettings() };
114
+ start(port, startOpts).then(actualPort => {
110
115
  const url = `http://localhost:${actualPort}/`;
111
116
  console.log(`\n▶ KingKont готов: ${url}`);
112
117
  if (targetPath) console.log(` подразумеваемый проект: ${targetPath}`);
package/main.js CHANGED
@@ -764,19 +764,41 @@ app.whenReady().then(async () => {
764
764
 
765
765
  // Фиксированный порт нужен потому что Chromium хранит IndexedDB и FSAH-handle
766
766
  // per-origin (http://localhost:PORT). Со случайным портом каждый запуск
767
- // получал бы новую пустую IDB. Если порт занят fallback на случайный, но
768
- // тогда recents-handle потеряется (это меньшая беда, чем падение запуска).
769
- // server.js на каждый запрос читает live-настройки через getSettings — это
770
- // позволяет переключать use*-флаги через UI без перезапуска. settings.json
771
- // на диске единственный источник правды; readSettings() делает свежий read.
767
+ // получал бы новую пустую IDB и юзер должен заново указывать папки в recents.
768
+ //
769
+ // RETRY на 17893: при relaunch'е старый instance отпускает singleton-lock
770
+ // быстрее, чем macOS освобождает TCP-сокет (TIME_WAIT). Без retry сразу
771
+ // падаем на random и теряем handle. 8×500мс = 4 сек обычно хватает.
772
+ // server.js на каждый запрос читает live-настройки через getSettings —
773
+ // settings.json на диске единственный источник правды.
772
774
  const startOpts = { getSettings: () => readSettings() };
773
- try {
774
- port = await start(17893, startOpts);
775
- } catch {
776
- console.warn('port 17893 busy, falling back to random');
775
+ const PRIMARY_PORT = 17893;
776
+ const RETRIES = 8;
777
+ let lastErr;
778
+ for (let i = 0; i < RETRIES; i++) {
779
+ try { port = await start(PRIMARY_PORT, startOpts); break; }
780
+ catch (e) {
781
+ lastErr = e;
782
+ if (e.code !== 'EADDRINUSE') break; // не race — нет смысла ретраить
783
+ console.warn(`port ${PRIMARY_PORT} busy (attempt ${i + 1}/${RETRIES}), waiting…`);
784
+ await new Promise(r => setTimeout(r, 500));
785
+ }
786
+ }
787
+ if (!port) {
788
+ // Сначала попробуем фиксированные fallback'и (17894/17895/...) —
789
+ // это сохранит хотя бы часть recents (origin будет стабильным от
790
+ // запуска к запуску при условии что 17893 хронически занят).
791
+ for (const p of [17894, 17895, 17896, 17897, 17898, 17899]) {
792
+ try { port = await start(p, startOpts); console.warn(`fell back to port ${p}`); break; }
793
+ catch { /* try next */ }
794
+ }
795
+ }
796
+ if (!port) {
797
+ // Последний резерв — случайный порт (потеряем handle).
798
+ console.warn('all stable ports busy, falling back to random (recents-handle will be lost)');
777
799
  try { port = await start(0, startOpts); }
778
800
  catch (e) {
779
- console.error('Server failed to start:', e);
801
+ console.error('Server failed to start:', e || lastErr);
780
802
  app.quit();
781
803
  return;
782
804
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.7.41",
3
+ "version": "0.7.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/skill/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: kingkont
3
- description: Use this skill when the user works with a KingKont project — a film/series scene editor where each scene is a folder with scene.json. Triggers — фразы вроде «открой/запусти kingkont», «открой редактор сцен», «добавь сцену/персонажа/локацию», «добавь ноду на холст», «сгенерируй картинку/видео/голос/SFX/музыку/текст», или работа с папкой содержащей _characters/ _locations/ <scene>/scene.json. Skill знает формат данных и использует CLI `kingkont <cmd>` (open/list/board/add-node/gen/connect/rm-node/upload/voices/balance) для управления нодами и запуска генераций — ключи берутся автоматически из настроек приложения. Для визуальной работы поднимает UI через `npx -y kingkont serve`.
3
+ description: Use this skill when the user works with a KingKont project — a film/series scene editor where each scene is a folder with scene.json. Triggers — фразы вроде «открой/запусти kingkont», «открой редактор сцен», «добавь сцену/персонажа/локацию», «добавь ноду на холст», «сгенерируй картинку/видео/голос/SFX/музыку/текст», или работа с папкой содержащей _characters/ _locations/ <scene>/scene.json. Skill знает формат данных и использует CLI `kingkont <cmd>` (open/list/board/add-node/gen/connect/rm-node/upload/voices/balance) для управления нодами и запуска генераций — ключи берутся автоматически из настроек приложения. ВАЖНО: каждая нода живёт в конкретной доске (сцене/персонаже/локации) — если юзер не указал доску явно, СПРОСИ его в какой добавить, не создавай новые сцены без явного запроса. Для визуальной работы поднимает UI через `npx -y kingkont serve`.
4
4
  ---
5
5
 
6
6
  # KingKont · Chatium — Skill
@@ -23,6 +23,42 @@ KingKont — нод-редактор сцен фильма/сериала с AI-
23
23
  - Любые правки тексту, перестановка нод, чистка истории, бэкап — все
24
24
  через прямую правку `scene.json` и `texts/*.md`.
25
25
 
26
+ ## ⚠️ ОБЯЗАТЕЛЬНОЕ ПРАВИЛО: всегда уточняй доску
27
+
28
+ **НИКОГДА не создавай новые сцены без явного запроса юзера.** Каждая нода
29
+ живёт в конкретной доске (сцене / персонаже / локации). Если юзер просит
30
+ «сгенерируй картинку», «добавь ноду», «вставь голос» — это значит
31
+ «внутри какой-то существующей доски», а не «создай новую».
32
+
33
+ ### Алгоритм перед любой операцией создания нод
34
+
35
+ 1. Запусти `kingkont open <project>` чтобы получить список существующих
36
+ досок проекта.
37
+ 2. Если юзер не указал доску явно — **спроси у него** в чём именно
38
+ работать:
39
+ - Если есть только одна сцена / `currentBoard` сохранён — используй её.
40
+ - Если несколько и юзер не уточнил — выведи нумерованный список и
41
+ спроси номер. Пример: «У тебя есть сцены: 1) Серия 1, 2) Серия 2,
42
+ 3) Серия 4.1. В какой добавить?»
43
+ 3. Не предлагай создать новую сцену пока юзер сам не попросит словами
44
+ вроде «новая сцена», «создай сцену», «добавь эпизод».
45
+ 4. Если юзер прислал N фото — все ноды идут в **одну** выбранную доску,
46
+ а не в N разных.
47
+
48
+ ### Как создавать новые сцены (только когда явно попросили)
49
+
50
+ Команды CLI для add-node — НЕ создают сцену; они работают только с
51
+ существующими досками. Чтобы создать новую сцену, нужно:
52
+
53
+ ```bash
54
+ mkdir -p <project>/<имя_новой_сцены>
55
+ echo '{"nodes":[],"connections":[]}' > <project>/<имя_новой_сцены>/scene.json
56
+ # Дальше — обычные kingkont add-node / kingkont gen с этой доской
57
+ ```
58
+
59
+ Аналогично для персонажа: `<project>/_characters/<имя>/scene.json`.
60
+ Для локации: `<project>/_locations/<имя>/scene.json`.
61
+
26
62
  ## Как открыть UI редактора
27
63
 
28
64
  ```bash
@@ -345,6 +381,34 @@ kingkont upload <file> # печатает публичный URL
345
381
 
346
382
  **«Открой редактор»** → `npx -y kingkont serve` + сообщить URL для Chrome.
347
383
 
384
+ ### Юзер просит сгенерировать что-то (картинку/видео/голос/SFX/текст)
385
+
386
+ **Сначала всегда** — определи доску. Не угадывай и не создавай новую.
387
+
388
+ ```bash
389
+ kingkont open <project> # JSON со списком всех досок
390
+ ```
391
+
392
+ Если юзер уже назвал доску в реплике («добавь в Серию 1», «на сцене Прощание»)
393
+ — используй её. Иначе спроси: «У тебя есть сцены: 1) Серия 1, 2) Серия 2,
394
+ 3) Серия 4.1. В какой добавить?» — и **жди ответа**.
395
+
396
+ Если юзер прислал несколько фото/референсов и сказал «вот, сгенери что-то по
397
+ ним» — это НЕ повод создать N новых сцен по одной на каждое фото. Это
398
+ повод спросить «в какой сцене разложить эти N кадров?».
399
+
400
+ После того как доска определена:
401
+
402
+ ```bash
403
+ kingkont gen <project> <board> --kind=image --prompt="..." --refs=@ref1
404
+ ```
405
+
406
+ ### Юзер просит добавить персонажа / локацию / новую сцену
407
+
408
+ Только тогда создавай папки. Триггерные фразы: «новая сцена», «добавь
409
+ сцену», «создай эпизод», «новый персонаж», «добавь персонажа», «новая
410
+ локация».
411
+
348
412
  **«Добавь персонажа Анна»**:
349
413
  ```bash
350
414
  mkdir -p <project>/_characters/Анна
@@ -354,26 +418,37 @@ kingkont gen <project> _characters/Анна --kind=image --name=sheet \
354
418
  --prompt="портрет молодой женщины-следователя" --model=nano-banana-2
355
419
  ```
356
420
 
357
- **«Добавь текстовую ноду на сцену "Прощание" с таким текстом …»**:
421
+ **«Создай новую сцену "Финал"»**:
422
+ ```bash
423
+ mkdir -p <project>/Финал
424
+ echo '{"nodes":[],"connections":[]}' > <project>/Финал/scene.json
425
+ ```
426
+ После этого можно сразу генерить ноды в неё:
427
+ ```bash
428
+ kingkont gen <project> Финал --kind=text --name=script --prompt="..."
429
+ ```
430
+
431
+ ### Узкие сценарии
432
+
433
+ **«Добавь текстовую ноду на сцену "Прощание"»**:
358
434
  ```bash
359
435
  kingkont add-node <project> Прощание --kind=text --name=plot --text="ТЕКСТ"
360
436
  ```
361
437
 
362
- **«Свяжи ноды @А и @Б»**:
438
+ **«Свяжи ноды @А и @Б»** (в одной доске):
363
439
  ```bash
364
440
  kingkont connect <project> Прощание А Б
365
441
  ```
366
442
 
367
- **«Сгенерируй SFX "камни сыпятся"»**:
443
+ **«Сгенерируй SFX "камни сыпятся" в Серии 1»**:
368
444
  ```bash
369
- kingkont gen <project> <board> --kind=audio --sub-kind=sfx \
445
+ kingkont gen <project> 'Серия 1' --kind=audio --sub-kind=sfx \
370
446
  --prompt="rocks falling, gravel cascading" --duration=3
371
447
  ```
372
448
  (SFX-модель ElevenLabs работает лучше на английском — переводи русский промпт.)
373
449
 
374
- **«Сделай i2v видео из этой картинки»**:
450
+ **«Сделай i2v видео из этой картинки»** (нода @hero уже в доске):
375
451
  ```bash
376
- # Нода @hero уже есть в этой доске:
377
452
  kingkont gen <project> <board> --kind=video --refs=@hero \
378
453
  --model=kling-3.0 --prompt="hero turns and walks away"
379
454
  ```