@wendongfly/myhi 1.3.210 → 1.3.212
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 +163 -12
- package/dist/chat.html.gz +0 -0
- package/dist/index.html +1 -1
- package/dist/index.html.gz +0 -0
- package/dist/index.js +1 -1
- package/dist/index.min.js +142 -141
- package/package.json +1 -1
package/dist/chat.html
CHANGED
|
@@ -693,6 +693,50 @@
|
|
|
693
693
|
#fedit-sheet.action-sheet.open { align-items: center; }
|
|
694
694
|
#fedit-sheet .action-sheet-box { width: 94vw; max-width: 1200px; border-radius: 14px; padding-bottom: 0.75rem; }
|
|
695
695
|
#memory-content { flex: 1; min-height: 0; }
|
|
696
|
+
/* 方案审批:手机全屏,电脑居中宽屏 + 左侧目录 */
|
|
697
|
+
#plan-sheet .plan-box { max-width: none; height: 100dvh; max-height: 100dvh; border-radius: 0; display: flex; flex-direction: column; padding: 0.5rem 0.75rem max(0.6rem, env(safe-area-inset-bottom)); }
|
|
698
|
+
@media (min-width: 768px) {
|
|
699
|
+
#plan-sheet.action-sheet.open { align-items: center; }
|
|
700
|
+
#plan-sheet .plan-box { width: 96vw; max-width: 1280px; height: 92vh; border-radius: 14px; }
|
|
701
|
+
}
|
|
702
|
+
.plan-head { display: flex; align-items: center; gap: 0.4rem; padding: 0.2rem 0 0.5rem; border-bottom: 1px solid var(--surface2); flex-wrap: wrap; font-size: 0.9rem; }
|
|
703
|
+
.plan-stat { font-size: 0.72rem; color: var(--muted); }
|
|
704
|
+
.plan-hbtn { background: var(--surface2); border: 1px solid var(--border); color: var(--text); border-radius: 8px; padding: 0.3rem 0.6rem; font-size: 0.78rem; cursor: pointer; white-space: nowrap; }
|
|
705
|
+
.plan-hbtn:hover { border-color: var(--purple); }
|
|
706
|
+
#plan-ai-btn { color: var(--purple); font-weight: 600; }
|
|
707
|
+
.plan-main { flex: 1; min-height: 0; display: flex; gap: 0.6rem; position: relative; padding-top: 0.4rem; }
|
|
708
|
+
#plan-toc { width: 230px; flex-shrink: 0; overflow-y: auto; font-size: 0.78rem; border-right: 1px solid var(--surface2); padding-right: 0.4rem; scrollbar-width: thin; }
|
|
709
|
+
#plan-toc a { display: block; padding: 0.28rem 0.4rem; border-radius: 6px; color: var(--text2, var(--text)); text-decoration: none; cursor: pointer; line-height: 1.35; }
|
|
710
|
+
#plan-toc a:hover, #plan-toc a.on { background: var(--surface2); color: var(--purple); }
|
|
711
|
+
#plan-toc a.l3 { padding-left: 1.1rem; font-size: 0.74rem; } #plan-toc a.l4 { padding-left: 1.8rem; font-size: 0.72rem; color: var(--muted); }
|
|
712
|
+
.plan-toc-btn { display: none; }
|
|
713
|
+
@media (max-width: 767px) {
|
|
714
|
+
#plan-toc { display: none; position: absolute; z-index: 3; left: 0; top: 0.4rem; bottom: 0; width: 78%; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 0.4rem; box-shadow: 0 6px 24px rgba(0,0,0,0.3); }
|
|
715
|
+
#plan-toc.show { display: block; }
|
|
716
|
+
.plan-toc-btn { display: inline-block; }
|
|
717
|
+
}
|
|
718
|
+
.plan-scroll { flex: 1; min-width: 0; overflow-y: auto; overflow-x: hidden; padding: 0.2rem 0.5rem; scrollbar-width: thin; }
|
|
719
|
+
#plan-sheet-body pre { white-space: pre-wrap; word-break: break-word; }
|
|
720
|
+
#plan-sheet-body code { word-break: break-all; }
|
|
721
|
+
#plan-sheet-body table { display: block; overflow-x: auto; }
|
|
722
|
+
#plan-digest { border: 1px solid var(--purple); border-radius: 10px; padding: 0.5rem 0.75rem; margin: 0.2rem 0 0.8rem; background: color-mix(in srgb, var(--purple) 6%, transparent); font-size: 0.86rem; }
|
|
723
|
+
#plan-digest .pd-h { display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: var(--muted); margin-bottom: 0.3rem; }
|
|
724
|
+
.plan-foot { border-top: 1px solid var(--surface2); padding-top: 0.5rem; }
|
|
725
|
+
#plan-sheet-fb { min-height: 5.5em; max-height: 40vh; resize: vertical; margin-bottom: 0.45rem; line-height: 1.5; }
|
|
726
|
+
.plan-btns { display: flex; flex-direction: column; gap: 0.4rem; }
|
|
727
|
+
.plan-btns .action-sheet-cancel { margin: 0; }
|
|
728
|
+
@media (min-width: 768px) { .plan-btns { flex-direction: row; } .plan-btns .action-sheet-cancel { flex: 1; } }
|
|
729
|
+
.plan-t-short { display: none; }
|
|
730
|
+
@media (max-width: 767px) {
|
|
731
|
+
.plan-t-long { display: none; } .plan-t-short { display: inline; }
|
|
732
|
+
.plan-head { flex-wrap: nowrap; } .plan-stat { display: none; }
|
|
733
|
+
#plan-sheet-fb { min-height: 3.2em; }
|
|
734
|
+
/* 批准占一整行,另外两个并排,给方案多留阅读空间 */
|
|
735
|
+
.plan-btns { display: grid; grid-template-columns: 1fr 1fr; }
|
|
736
|
+
.plan-btns .action-sheet-cancel:first-child { grid-column: 1 / -1; }
|
|
737
|
+
}
|
|
738
|
+
#plan-quote-btn { display: none; position: fixed; z-index: 95; background: var(--purple); color: #fff; border: none; border-radius: 8px; padding: 0.4rem 0.75rem; font-size: 0.8rem; box-shadow: 0 4px 14px rgba(0,0,0,0.3); cursor: pointer; }
|
|
739
|
+
#plan-quote-btn.show { display: block; }
|
|
696
740
|
.slash-inp { width: 100%; padding: 0.65rem 0.8rem; background: var(--bg); border: 1px solid var(--border); border-radius: 10px; color: var(--text); font-size: 0.9rem; outline: none; }
|
|
697
741
|
.slash-inp:focus { border-color: var(--purple); }
|
|
698
742
|
|
|
@@ -1348,17 +1392,36 @@
|
|
|
1348
1392
|
</div>
|
|
1349
1393
|
</div>
|
|
1350
1394
|
<!-- 方案审批:计划模式下 AI 用 ExitPlanMode 提交方案 -->
|
|
1395
|
+
<!-- 长方案也要审得动:电脑上宽屏 + 左侧目录,手机全屏;「AI 帮我看重点」先出摘要;选中一段可引用到意见框 -->
|
|
1351
1396
|
<div id="plan-sheet" class="action-sheet">
|
|
1352
1397
|
<div class="action-sheet-backdrop" onclick="closePlanSheet()"></div>
|
|
1353
|
-
<div class="action-sheet-box
|
|
1354
|
-
<div class="
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1398
|
+
<div class="action-sheet-box plan-box">
|
|
1399
|
+
<div class="plan-head">
|
|
1400
|
+
<b>📋 <span class="plan-t-long">AI 提交了方案,请审批</span><span class="plan-t-short">方案审批</span></b>
|
|
1401
|
+
<span id="plan-stat" class="plan-stat"></span>
|
|
1402
|
+
<span style="flex:1"></span>
|
|
1403
|
+
<button class="plan-hbtn" id="plan-ai-btn" onclick="planDigest()" title="用「问一问」的模型先把方案读一遍:概括、会改什么、需要你确认的、风险、可以提的意见">✨ AI 帮我看重点</button>
|
|
1404
|
+
<button class="plan-hbtn plan-toc-btn" onclick="togglePlanToc()">☰ 目录</button>
|
|
1405
|
+
<button class="plan-hbtn" onclick="closePlanSheet()" title="稍后再看">✕</button>
|
|
1406
|
+
</div>
|
|
1407
|
+
<div class="plan-main">
|
|
1408
|
+
<nav id="plan-toc"></nav>
|
|
1409
|
+
<div class="plan-scroll msg-assistant" id="plan-scroll">
|
|
1410
|
+
<div id="plan-digest" style="display:none"></div>
|
|
1411
|
+
<div class="content" id="plan-sheet-body"></div>
|
|
1412
|
+
</div>
|
|
1413
|
+
</div>
|
|
1414
|
+
<div class="plan-foot">
|
|
1415
|
+
<textarea id="plan-sheet-fb" class="slash-inp" rows="3" placeholder="修改意见(可选):直接写;或在上面选中一段文字,点「💬 对这段提意见」把它引用过来,再写意见"></textarea>
|
|
1416
|
+
<div class="plan-btns">
|
|
1417
|
+
<button class="action-sheet-cancel" style="background:var(--green);color:#fff;font-weight:600" onclick="approvePlan()">✅ 批准并执行</button>
|
|
1418
|
+
<button class="action-sheet-cancel" onclick="revisePlan()">✏️ 按意见修改方案</button>
|
|
1419
|
+
<button class="action-sheet-cancel" onclick="closePlanSheet()">稍后再看</button>
|
|
1420
|
+
</div>
|
|
1421
|
+
</div>
|
|
1360
1422
|
</div>
|
|
1361
1423
|
</div>
|
|
1424
|
+
<button id="plan-quote-btn" onmousedown="event.preventDefault()" onclick="planQuoteSel()">💬 对这段提意见</button>
|
|
1362
1425
|
<!-- 退出计划:按方案执行 / 仅退出 -->
|
|
1363
1426
|
<div id="planexit-sheet" class="action-sheet">
|
|
1364
1427
|
<div class="action-sheet-backdrop" onclick="closePlanExit()"></div>
|
|
@@ -2623,10 +2686,10 @@
|
|
|
2623
2686
|
if (syntheticUserKind(msg.content)) return;
|
|
2624
2687
|
// 看图转文字后发给模型的消息(对话记录里就是改写后的全文):气泡只显示原话,图片描述收进折叠块
|
|
2625
2688
|
let content = msg.content, vis = null;
|
|
2626
|
-
const vi = typeof content === 'string' ? content.
|
|
2689
|
+
const vi = typeof content === 'string' ? content.search(/\n\n(注意:(你当前用的模型不能直接看图|myhi 已用看图模型)/) : -1; // 新旧两种措辞
|
|
2627
2690
|
if (vi > 0) {
|
|
2628
2691
|
const tail = content.slice(vi);
|
|
2629
|
-
vis = { message: '', vision: { model: (tail.match(/看图模型 (\S+)
|
|
2692
|
+
vis = { message: '', vision: { model: (tail.match(/看图模型 (\S+) 把/) || [])[1] || '',
|
|
2630
2693
|
items: [...tail.matchAll(/【图片 ([^】]+)】\n([\s\S]*?)(?=\n\n【图片 |$)/g)].map(m => ({ path: m[1], text: m[2] })) } };
|
|
2631
2694
|
content = content.slice(0, vi);
|
|
2632
2695
|
}
|
|
@@ -5581,12 +5644,100 @@
|
|
|
5581
5644
|
if (_askCtlId) document.getElementById('ask-sheet').classList.add('open');
|
|
5582
5645
|
};
|
|
5583
5646
|
// ── 方案审批 ──
|
|
5647
|
+
let _planDigest = { id: null, text: '', state: '' }; // AI 重点速览:按方案 id 缓存,关了再开不重复花钱
|
|
5648
|
+
let _planDigestReq = null;
|
|
5584
5649
|
window.openPlanSheet = function() {
|
|
5585
5650
|
if (!_planCtl) return;
|
|
5586
|
-
|
|
5651
|
+
const plan = _planCtl.plan || '(方案为空)';
|
|
5652
|
+
const body = document.getElementById('plan-sheet-body');
|
|
5653
|
+
body.innerHTML = renderMarkdown(plan);
|
|
5654
|
+
// 目录:方案里的标题(# ~ ####),点了跳到对应位置
|
|
5655
|
+
const hs = [...body.querySelectorAll('h1,h2,h3,h4')];
|
|
5656
|
+
const minL = Math.min(...hs.map(h => +h.tagName[1]), 9);
|
|
5657
|
+
document.getElementById('plan-toc').innerHTML = hs.length < 2 ? '<div style="color:var(--muted);padding:0.4rem">这份方案没有分节标题</div>'
|
|
5658
|
+
: hs.map((h, i) => { h.id = 'plan-h-' + i; return `<a class="l${Math.min(4, h.tagName[1] - minL + 2)}" data-i="${i}">${escHtml(h.textContent.trim())}</a>`; }).join('');
|
|
5659
|
+
document.getElementById('plan-toc').querySelectorAll('a').forEach(a => a.onclick = () => {
|
|
5660
|
+
document.getElementById('plan-h-' + a.dataset.i)?.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
|
5661
|
+
document.getElementById('plan-toc').classList.remove('show');
|
|
5662
|
+
});
|
|
5663
|
+
const chars = plan.replace(/\s/g, '').length;
|
|
5664
|
+
document.getElementById('plan-stat').textContent = `约 ${chars} 字${hs.length ? ` · ${hs.length} 节` : ''} · 约 ${Math.max(1, Math.round(chars / 500))} 分钟读完`;
|
|
5665
|
+
document.getElementById('plan-scroll').scrollTop = 0;
|
|
5666
|
+
renderPlanDigest();
|
|
5587
5667
|
document.getElementById('plan-sheet').classList.add('open');
|
|
5588
5668
|
};
|
|
5589
|
-
window.closePlanSheet = function() {
|
|
5669
|
+
window.closePlanSheet = function() {
|
|
5670
|
+
document.getElementById('plan-sheet').classList.remove('open');
|
|
5671
|
+
document.getElementById('plan-quote-btn').classList.remove('show');
|
|
5672
|
+
renderPendingBar();
|
|
5673
|
+
};
|
|
5674
|
+
window.togglePlanToc = function() { document.getElementById('plan-toc').classList.toggle('show'); };
|
|
5675
|
+
// 目录高亮:滚到哪一节就亮哪一节
|
|
5676
|
+
document.getElementById('plan-scroll').addEventListener('scroll', () => {
|
|
5677
|
+
const sc = document.getElementById('plan-scroll'), top = sc.getBoundingClientRect().top + 40;
|
|
5678
|
+
let cur = null;
|
|
5679
|
+
sc.querySelectorAll('#plan-sheet-body [id^="plan-h-"]').forEach(h => { if (h.getBoundingClientRect().top <= top) cur = h.id.slice(7); });
|
|
5680
|
+
document.querySelectorAll('#plan-toc a').forEach(a => a.classList.toggle('on', a.dataset.i === cur));
|
|
5681
|
+
}, { passive: true });
|
|
5682
|
+
// 意见框按内容长高(最多 40% 屏高)
|
|
5683
|
+
document.getElementById('plan-sheet-fb').addEventListener('input', (e) => {
|
|
5684
|
+
const t = e.target; t.style.height = 'auto'; t.style.height = Math.min(t.scrollHeight + 2, innerHeight * 0.4) + 'px';
|
|
5685
|
+
});
|
|
5686
|
+
// ✨ AI 帮我看重点:走「问一问」那条通道(问一问 / 解释的场景模型),不进当前会话、不打扰 AI
|
|
5687
|
+
const PLAN_DIGEST_Q = '请帮用户审这份方案。用中文、简洁,按下面的结构输出,每项 1~5 条要点,尽量引用方案里的原词方便用户定位;没有的项写「无」,不要复述全文:\n' +
|
|
5688
|
+
'### 一句话概括\n### 会改动什么(模块 / 文件 / 数据库 / 接口 / 配置)\n### 需要你确认或提供的(凭据、权限、取舍决定等)\n### 风险与容易出错的地方\n### 可以提的修改意见 / 建议追问';
|
|
5689
|
+
function renderPlanDigest() {
|
|
5690
|
+
const box = document.getElementById('plan-digest'), btn = document.getElementById('plan-ai-btn');
|
|
5691
|
+
const mine = _planCtl && _planDigest.id === _planCtl.id;
|
|
5692
|
+
if (!mine || !_planDigest.state) { box.style.display = 'none'; btn.textContent = '✨ AI 帮我看重点'; btn.disabled = false; return; }
|
|
5693
|
+
box.style.display = '';
|
|
5694
|
+
const busy = _planDigest.state === 'busy';
|
|
5695
|
+
btn.textContent = busy ? '⏳ 正在看…' : '✨ 重新生成'; btn.disabled = busy;
|
|
5696
|
+
box.innerHTML = `<div class="pd-h"><b style="color:var(--purple)">✨ 重点速览</b><span>由「问一问」模型生成,仅供参考,以下面方案原文为准</span>${busy ? '' : '<span style="flex:1"></span><a style="cursor:pointer;color:var(--muted)" onclick="document.getElementById(\'plan-digest\').style.display=\'none\'">收起</a>'}</div>` +
|
|
5697
|
+
(_planDigest.err ? `<div style="color:var(--red)">没能生成:${escHtml(_planDigest.err)}</div>` : '') +
|
|
5698
|
+
`<div class="content">${_planDigest.text ? renderMarkdown(_planDigest.text) : '<span style="color:var(--muted)">AI 正在读方案…</span>'}</div>`;
|
|
5699
|
+
}
|
|
5700
|
+
window.planDigest = function() {
|
|
5701
|
+
if (!_planCtl) return;
|
|
5702
|
+
_planDigestReq = 'plan-' + Date.now();
|
|
5703
|
+
_planDigest = { id: _planCtl.id, text: '', state: 'busy' };
|
|
5704
|
+
renderPlanDigest();
|
|
5705
|
+
document.getElementById('plan-scroll').scrollTop = 0;
|
|
5706
|
+
socket.emit('aside:ask', { reqId: _planDigestReq, kind: 'plan', context: _planCtl.plan || '', question: PLAN_DIGEST_Q, userAsk: '' });
|
|
5707
|
+
};
|
|
5708
|
+
socket.on('aside:delta', ({ reqId, text }) => { if (reqId === _planDigestReq) { _planDigest.text = text; renderPlanDigest(); } });
|
|
5709
|
+
socket.on('aside:done', ({ reqId, text, error, partial }) => {
|
|
5710
|
+
if (reqId !== _planDigestReq) return;
|
|
5711
|
+
_planDigestReq = null;
|
|
5712
|
+
_planDigest.text = text || partial || _planDigest.text; _planDigest.err = text ? '' : (error || '没有拿到结果,稍后再试');
|
|
5713
|
+
_planDigest.state = 'done'; renderPlanDigest();
|
|
5714
|
+
});
|
|
5715
|
+
// 选中方案(或速览)里的一段 → 「💬 对这段提意见」:以引用格式追加到意见框
|
|
5716
|
+
let _planSel = '';
|
|
5717
|
+
document.addEventListener('selectionchange', () => {
|
|
5718
|
+
const btn = document.getElementById('plan-quote-btn');
|
|
5719
|
+
const sel = window.getSelection();
|
|
5720
|
+
const text = sel && !sel.isCollapsed ? sel.toString().trim() : '';
|
|
5721
|
+
const node = text && sel.anchorNode && (sel.anchorNode.nodeType === 1 ? sel.anchorNode : sel.anchorNode.parentElement);
|
|
5722
|
+
if (!text || !node?.closest?.('#plan-scroll') || !document.getElementById('plan-sheet').classList.contains('open')) { _planSel = ''; btn.classList.remove('show'); return; }
|
|
5723
|
+
_planSel = text;
|
|
5724
|
+
btn.classList.add('show');
|
|
5725
|
+
const r = sel.getRangeAt(0).getBoundingClientRect(), bw = btn.offsetWidth, bh = btn.offsetHeight;
|
|
5726
|
+
let top = r.top - bh - 8; if (top < 8) top = r.bottom + 8;
|
|
5727
|
+
btn.style.left = Math.min(innerWidth - bw - 8, Math.max(8, r.left + r.width / 2 - bw / 2)) + 'px';
|
|
5728
|
+
btn.style.top = top + 'px';
|
|
5729
|
+
});
|
|
5730
|
+
window.planQuoteSel = function() {
|
|
5731
|
+
if (!_planSel) return;
|
|
5732
|
+
const fb = document.getElementById('plan-sheet-fb');
|
|
5733
|
+
const quote = _planSel.split('\n').map(l => '> ' + l).join('\n');
|
|
5734
|
+
const cur = fb.value.replace(/\s+$/, '');
|
|
5735
|
+
fb.value = (cur ? cur + '\n\n' : '') + quote + '\n';
|
|
5736
|
+
window.getSelection()?.removeAllRanges();
|
|
5737
|
+
document.getElementById('plan-quote-btn').classList.remove('show');
|
|
5738
|
+
fb.dispatchEvent(new Event('input'));
|
|
5739
|
+
fb.focus(); fb.setSelectionRange(fb.value.length, fb.value.length); fb.scrollTop = fb.scrollHeight;
|
|
5740
|
+
};
|
|
5590
5741
|
window.approvePlan = function() {
|
|
5591
5742
|
if (!_planCtl) return;
|
|
5592
5743
|
ensureControl();
|
|
@@ -5599,7 +5750,7 @@
|
|
|
5599
5750
|
if (!fb) { document.getElementById('plan-sheet-fb').focus(); document.getElementById('plan-sheet-fb').placeholder = '先写下要怎么改,再点这个按钮'; return; }
|
|
5600
5751
|
ensureControl();
|
|
5601
5752
|
socket.emit('agent:respond', { id: _planCtl.id, decision: { approve: false, feedback: fb } });
|
|
5602
|
-
document.getElementById('plan-sheet-fb').value = '';
|
|
5753
|
+
document.getElementById('plan-sheet-fb').value = ''; document.getElementById('plan-sheet-fb').style.height = '';
|
|
5603
5754
|
_planCtl = null; closePlanSheet(); showThinking();
|
|
5604
5755
|
};
|
|
5605
5756
|
// ── 聊天里的方案卡片:ExitPlanMode 提交的方案、写进 ~/.claude/plans/*.md 的方案文件(原来只是个折叠的「写文件」,看不到内容)──
|
package/dist/chat.html.gz
CHANGED
|
Binary file
|
package/dist/index.html
CHANGED
|
@@ -1519,7 +1519,7 @@
|
|
|
1519
1519
|
background: '生成标题、摘要等后台小活,建议选便宜的',
|
|
1520
1520
|
ask: '「问一问」和解释,建议选便宜快速的;留空 = sonnet',
|
|
1521
1521
|
voice: '语音转成书面文字,建议选便宜的;留空 = 同问一问',
|
|
1522
|
-
vision: '
|
|
1522
|
+
vision: '配了就用:聊天框发的图片先用它转成文字再交给主模型(多花几秒,聊天里可点开核对);主模型看不了图时一定要配。留空 = 图片直接发给主模型',
|
|
1523
1523
|
};
|
|
1524
1524
|
// ── 大模型网关 ────────────────────────────────────────────
|
|
1525
1525
|
const GW_SRC = { myhi: '本页配置', env: '启动 myhi 时的环境变量(ANTHROPIC_BASE_URL)', claude: 'Claude Code 配置(~/.claude/settings.json)' };
|
package/dist/index.html.gz
CHANGED
|
Binary file
|