@wendongfly/myhi 1.3.147 → 1.3.149

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/dist/chat.html CHANGED
@@ -192,6 +192,11 @@
192
192
  .msg-history .code-block { background: var(--bg); border: 1px solid var(--surface2); border-radius: 8px; padding: 0.6rem 0.75rem; font-family: 'SF Mono', 'Consolas', monospace; font-size: 0.75rem; line-height: 1.3; white-space: pre-wrap; word-break: break-all; color: var(--muted); max-height: 300px; overflow-y: auto; }
193
193
  .msg-history .meta { font-size: 0.65rem; color: var(--dimmer); margin-bottom: 4px; }
194
194
  .msg-status { text-align: center; font-size: 0.75rem; color: var(--muted); padding: 0.5rem 0; }
195
+ /* claude CLI 注入的合成 user 消息(上下文压缩续接摘要)—— 系统面板,不长成用户发言 */
196
+ .msg-synthetic { margin: 0.4rem 0; }
197
+ .msg-synthetic .syn-head { text-align: center; font-size: 0.75rem; color: var(--muted); cursor: pointer; user-select: none; padding: 0.35rem 0; }
198
+ .msg-synthetic .syn-head:hover { color: var(--text); }
199
+ .msg-synthetic .syn-body { white-space: pre-wrap; font-family: 'SF Mono', 'Cascadia Code', 'Consolas', monospace; font-size: 0.75rem; line-height: 1.5; color: var(--muted); background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem 0.75rem; max-height: 320px; overflow-y: auto; word-break: break-word; }
195
200
 
196
201
  /* ── 输入栏 ─────────────────────────────── */
197
202
  #input-area { background: var(--surface); border-top: 1px solid var(--border); flex-shrink: 0; padding: 0.5rem 0.75rem 0.35rem; }
@@ -1503,6 +1508,49 @@
1503
1508
  scrollToBottom();
1504
1509
  }
1505
1510
 
1511
+ // claude CLI 自己注入的「合成 user 消息」——不是真人打的字:
1512
+ // ① 上下文满时 claude 自动压缩续接,往 transcript 写一大段 "This session is being
1513
+ // continued..." 英文摘要(isCompactSummary);重启/重进回放时若照用户气泡渲染,
1514
+ // 看起来就像有人在你会话里打字(实际反馈过)。
1515
+ // ② [Request interrupted by user]:点停止按钮产生的中断标记,同理不是发言。
1516
+ // 分别渲染成折叠摘要面板 / 状态行。
1517
+ function syntheticUserKind(text) {
1518
+ if (typeof text !== 'string') return null;
1519
+ const t = text.trimStart();
1520
+ if (t.startsWith('This session is being continued from a previous conversation')) return 'compact';
1521
+ if (t.startsWith('[Request interrupted by user')) return 'interrupt'; // 含 "...for tool use" 变体
1522
+ return null;
1523
+ }
1524
+
1525
+ function buildSyntheticUserEl(content) {
1526
+ const el = document.createElement('div');
1527
+ if (syntheticUserKind(content) === 'interrupt') {
1528
+ el.className = 'msg msg-status';
1529
+ el.textContent = '— ⏹ 请求已中断 —';
1530
+ return el;
1531
+ }
1532
+ el.className = 'msg msg-synthetic';
1533
+ const head = document.createElement('div');
1534
+ head.className = 'syn-head';
1535
+ const body = document.createElement('div');
1536
+ body.className = 'syn-body';
1537
+ body.style.display = 'none';
1538
+ body.textContent = content; // 摘要可能带任意字符,textContent 防注入
1539
+ const sync = () => {
1540
+ head.textContent = body.style.display !== 'none'
1541
+ ? '🔄 上下文已满,claude 已自动压缩续接(点此收起摘要)'
1542
+ : '🔄 上下文已满,claude 已自动压缩续接(点此展开摘要)';
1543
+ };
1544
+ head.onclick = () => {
1545
+ body.style.display = body.style.display !== 'none' ? 'none' : 'block';
1546
+ sync();
1547
+ };
1548
+ sync();
1549
+ el.appendChild(head);
1550
+ el.appendChild(body);
1551
+ return el;
1552
+ }
1553
+
1506
1554
  // 连续重复的同一条状态不再一行行堆,折叠成「— xxx — ×N」。
1507
1555
  // 任何会反复触发的状态(自动重启、上传失败、控制权变更…)都不会再刷屏。
1508
1556
  function addStatusMessage(text) {
@@ -2329,7 +2377,13 @@
2329
2377
  endStream(); // 每条历史消息都是独立的,不要流式合并
2330
2378
  if (subaRoute(msg)) continue; // 子代理内部历史消息归入对应面板
2331
2379
  if (msg.type === 'user' && msg.content) {
2332
- addInputMessage(msg.content);
2380
+ // claude 注入的合成消息(压缩续接摘要/中断标记)渲染成系统面板,不长成用户发言
2381
+ if (syntheticUserKind(msg.content)) {
2382
+ chatArea.appendChild(buildSyntheticUserEl(msg.content));
2383
+ trimMessages(); scrollToBottom();
2384
+ } else {
2385
+ addInputMessage(msg.content);
2386
+ }
2333
2387
  } else if (msg.type === 'assistant' && msg.message?.content) {
2334
2388
  // 将同一条 assistant 消息的所有 text block 合并为一条
2335
2389
  const texts = [];
@@ -2411,10 +2465,14 @@
2411
2465
  const frag = document.createDocumentFragment();
2412
2466
  for (const msg of d.messages) {
2413
2467
  if (msg.type === 'user' && msg.content) {
2414
- const el = document.createElement('div');
2415
- el.className = 'msg msg-input';
2416
- el.innerHTML = `<div><div class="bubble">${escHtml(msg.content)}</div><div class="meta">${msg.timestamp ? new Date(msg.timestamp).toLocaleString('zh-CN') : ''}</div></div>`;
2417
- frag.appendChild(el);
2468
+ if (syntheticUserKind(msg.content)) {
2469
+ frag.appendChild(buildSyntheticUserEl(msg.content));
2470
+ } else {
2471
+ const el = document.createElement('div');
2472
+ el.className = 'msg msg-input';
2473
+ el.innerHTML = `<div><div class="bubble">${escHtml(msg.content)}</div><div class="meta">${msg.timestamp ? new Date(msg.timestamp).toLocaleString('zh-CN') : ''}</div></div>`;
2474
+ frag.appendChild(el);
2475
+ }
2418
2476
  } else if (msg.type === 'assistant' && msg.message?.content) {
2419
2477
  const texts = [], tools = [];
2420
2478
  for (const block of msg.message.content) {