kingkont 0.11.2 → 0.11.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "KingKont · Chatium — нод-редактор сцен с AI-генерацией (картинки/видео/голос/SFX/музыка/текст)",
5
5
  "main": "main.js",
6
6
  "bin": {
package/renderer/chat.js CHANGED
@@ -269,9 +269,13 @@
269
269
  // <tool>JSON</tool> — наш command-protocol (модель так зовёт tools)
270
270
  // <tool_result>JSON</tool_result> — модель иногда его галюцинирует
271
271
  // в outputе, копируя format из user-msg.
272
+ // После стрипа нормализуем whitespace — иначе остаются «дыры» и
273
+ // подряд идущие space'ы (3+ → 1, blank lines 3+ → 2).
272
274
  return text
273
275
  .replace(/<tool>[\s\S]*?<\/tool>/g, '')
274
276
  .replace(/<tool_result>[\s\S]*?<\/tool_result>/g, '')
277
+ .replace(/[ \t]{2,}/g, ' ')
278
+ .replace(/\n{3,}/g, '\n\n')
275
279
  .trim();
276
280
  }
277
281
 
@@ -518,26 +522,42 @@
518
522
  for (const m of history) {
519
523
  if (m.role === 'system') continue;
520
524
  if (m.role === 'user' && m.content?.startsWith('<tool_result>')) continue; // системный turn
525
+ // Пустой assistant без tools — не рендерим (бывает при streaming/parse-fail).
526
+ const hasContent = !!(m.content && m.content.trim());
527
+ const hasTools = Array.isArray(m.tools) && m.tools.length;
528
+ if (!hasContent && !hasTools) continue;
521
529
  const div = document.createElement('div');
522
530
  div.className = 'chat-msg chat-msg-' + m.role;
523
531
  const lbl = document.createElement('div');
524
532
  lbl.className = 'chat-msg-role';
525
533
  lbl.textContent = m.role === 'user' ? 'Вы' : 'Claude';
526
534
  div.appendChild(lbl);
527
- const body = document.createElement('div');
528
- body.className = 'chat-msg-body';
529
- body.textContent = m.content || '';
530
- div.appendChild(body);
531
- if (Array.isArray(m.tools) && m.tools.length) {
535
+ if (hasContent) {
536
+ const body = document.createElement('div');
537
+ body.className = 'chat-msg-body';
538
+ body.textContent = m.content;
539
+ div.appendChild(body);
540
+ }
541
+ if (hasTools) {
532
542
  for (const tc of m.tools) {
533
543
  const t = document.createElement('details');
534
544
  t.className = 'chat-tool';
535
545
  const sum = document.createElement('summary');
536
- sum.textContent = `🔧 ${tc.name}` + (tc._error ? ' (ошибка)' : tc._ok ? ' ✓' : '');
546
+ // Компактный summary: имя tool + ключевой arg (если короткий) + статус.
547
+ const argHint = _argHint(tc.args);
548
+ const status = tc._error ? ' ⚠' : tc._ok ? ' ✓' : '';
549
+ sum.textContent = `🔧 ${tc.name}${argHint}${status}`;
537
550
  t.appendChild(sum);
538
- const pre = document.createElement('pre');
539
- pre.textContent = JSON.stringify({ args: tc.args, result: tc.result, error: tc._error }, null, 2);
540
- t.appendChild(pre);
551
+ // pre добавляем только если есть что показать (args/result/error не пусты).
552
+ const dump = {};
553
+ if (tc.args && Object.keys(tc.args).length) dump.args = tc.args;
554
+ if (tc.result !== undefined) dump.result = tc.result;
555
+ if (tc._error) dump.error = tc._error;
556
+ if (Object.keys(dump).length) {
557
+ const pre = document.createElement('pre');
558
+ pre.textContent = JSON.stringify(dump, null, 2);
559
+ t.appendChild(pre);
560
+ }
541
561
  div.appendChild(t);
542
562
  }
543
563
  }
@@ -545,6 +565,22 @@
545
565
  }
546
566
  list.scrollTop = list.scrollHeight;
547
567
  }
568
+
569
+ // Короткая подсказка про args для summary tool-блока.
570
+ // 'add_node({type:image, name:"..."})' — без полного JSON.
571
+ function _argHint(args) {
572
+ if (!args || typeof args !== 'object') return '';
573
+ const keys = Object.keys(args);
574
+ if (!keys.length) return '';
575
+ const items = [];
576
+ for (const k of keys) {
577
+ const v = args[k];
578
+ let s = typeof v === 'string' ? `"${v.length > 30 ? v.slice(0, 30) + '…' : v}"` : String(v);
579
+ items.push(`${k}:${s}`);
580
+ if (items.join(',').length > 60) break;
581
+ }
582
+ return ` (${items.join(', ')})`;
583
+ }
548
584
  // Перебиндим
549
585
  renderHistory = renderHistoryFiltered;
550
586
 
@@ -269,13 +269,13 @@
269
269
  }
270
270
  .chat-header button:hover { background: #2a2a2a; color: #fff; }
271
271
  .chat-list {
272
- flex: 1; overflow-y: auto; padding: 12px;
273
- display: flex; flex-direction: column; gap: 12px;
272
+ flex: 1; overflow-y: auto; padding: 10px;
273
+ display: flex; flex-direction: column; gap: 6px;
274
274
  }
275
275
  .chat-msg {
276
- display: flex; flex-direction: column; gap: 4px;
277
- padding: 10px 12px; border-radius: 8px;
278
- font-size: 13px; line-height: 1.5;
276
+ display: flex; flex-direction: column; gap: 2px;
277
+ padding: 6px 10px; border-radius: 6px;
278
+ font-size: 13px; line-height: 1.45;
279
279
  }
280
280
  .chat-msg-user { background: #1f2a3a; border: 1px solid #2a3a4a; }
281
281
  .chat-msg-assistant { background: #1f1f1f; border: 1px solid #2a2a2a; }
@@ -289,8 +289,8 @@
289
289
  color: #e0e0e0; white-space: pre-wrap; word-break: break-word;
290
290
  }
291
291
  .chat-tool {
292
- margin-top: 6px; background: #0e0e0e; border: 1px solid #2a2a2a;
293
- border-radius: 4px; padding: 4px 8px; font-size: 11px;
292
+ margin-top: 2px; background: #0e0e0e; border: 1px solid #2a2a2a;
293
+ border-radius: 3px; padding: 2px 6px; font-size: 11px;
294
294
  }
295
295
  .chat-tool summary {
296
296
  cursor: pointer; color: #aac; outline: none;