@wendongfly/myhi 1.3.31 → 1.3.33
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 +132 -10
- package/package.json +1 -1
package/dist/chat.html
CHANGED
|
@@ -62,6 +62,14 @@
|
|
|
62
62
|
.msg-assistant .content pre code { background: none; padding: 0; }
|
|
63
63
|
.msg-assistant .content ul, .msg-assistant .content ol { padding-left: 1.5rem; margin: 0.3rem 0; }
|
|
64
64
|
.msg-assistant .content strong { color: #fff; }
|
|
65
|
+
.msg-assistant .content a { color: #58a6ff; text-decoration: none; word-break: break-all; }
|
|
66
|
+
.msg-assistant .content a:hover { text-decoration: underline; }
|
|
67
|
+
.md-table { border-collapse: collapse; margin: 0.5rem 0; font-size: 0.82rem; width: 100%; display: block; overflow-x: auto; white-space: nowrap; }
|
|
68
|
+
.md-table thead { background: #161b22; }
|
|
69
|
+
.md-table th, .md-table td { border: 1px solid #30363d; padding: 0.4rem 0.7rem; text-align: left; }
|
|
70
|
+
.md-table th { color: #fff; font-weight: 600; }
|
|
71
|
+
.md-table tbody tr:nth-child(even) { background: #0d1117; }
|
|
72
|
+
.md-table tbody tr:hover { background: #1c2128; }
|
|
65
73
|
|
|
66
74
|
/* 工具调用组 */
|
|
67
75
|
.msg-tool-group { border-left: 3px solid #58a6ff; margin-left: 0.3rem; padding-left: 0.6rem; margin-bottom: 0.3rem; }
|
|
@@ -327,7 +335,7 @@
|
|
|
327
335
|
</div>
|
|
328
336
|
<div id="sk-claude-agent" style="display:none">
|
|
329
337
|
<button class="sk sk-claude" onclick="openModelSheet()">模型</button>
|
|
330
|
-
<button class="sk sk-claude" onclick="
|
|
338
|
+
<button class="sk sk-claude" id="btn-plan" onclick="togglePlanMode()">计划</button>
|
|
331
339
|
<button class="sk sk-claude" onclick="doSlashCmd('/compact')">压缩</button>
|
|
332
340
|
<button class="sk sk-claude" onclick="openResumeSheet()">恢复</button>
|
|
333
341
|
<button class="sk sk-claude" onclick="doClear()">清除</button>
|
|
@@ -465,6 +473,20 @@
|
|
|
465
473
|
</div>
|
|
466
474
|
</div>
|
|
467
475
|
|
|
476
|
+
<!-- 运行自定义命令 (输入参数) 弹窗 -->
|
|
477
|
+
<div id="skill-run-sheet" class="action-sheet">
|
|
478
|
+
<div class="action-sheet-backdrop" onclick="closeSkillRunSheet()"></div>
|
|
479
|
+
<div class="action-sheet-box" style="max-height:60vh;display:flex;flex-direction:column">
|
|
480
|
+
<div class="action-sheet-title" id="skill-run-title">/命令</div>
|
|
481
|
+
<div id="skill-run-desc" style="padding:0.3rem 0.5rem;font-size:0.78rem;color:#8b949e;line-height:1.5;white-space:pre-wrap"></div>
|
|
482
|
+
<div style="padding:0.3rem 0.2rem">
|
|
483
|
+
<textarea id="skill-run-input" class="slash-inp" placeholder="补充要求(可选),如项目范围、额外约束等" rows="3" style="resize:vertical"></textarea>
|
|
484
|
+
</div>
|
|
485
|
+
<button class="action-sheet-cancel" style="background:#7c3aed;color:#fff;font-weight:600;margin-bottom:0.4rem" onclick="submitSkillRun()">执行</button>
|
|
486
|
+
<button class="action-sheet-cancel" onclick="closeSkillRunSheet()">取消</button>
|
|
487
|
+
</div>
|
|
488
|
+
</div>
|
|
489
|
+
|
|
468
490
|
<!-- AskUserQuestion 弹窗 -->
|
|
469
491
|
<div id="ask-sheet" class="action-sheet">
|
|
470
492
|
<div class="action-sheet-backdrop" onclick="closeAskSheet()"></div>
|
|
@@ -664,7 +686,21 @@
|
|
|
664
686
|
let html = '';
|
|
665
687
|
let inCode = false, codeLang = '', codeLines = [];
|
|
666
688
|
|
|
667
|
-
|
|
689
|
+
// 行内格式化辅助函数
|
|
690
|
+
const fmtInline = (s) => s
|
|
691
|
+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
692
|
+
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
693
|
+
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
|
694
|
+
.replace(/\[([^\]]+)\]\((https?:\/\/[^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');
|
|
695
|
+
|
|
696
|
+
// 表格检测:| ... | 后跟 |---|---| 分隔行
|
|
697
|
+
const isTableRow = (s) => /^\s*\|(.+)\|\s*$/.test(s);
|
|
698
|
+
const isTableSep = (s) => /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)+\|?\s*$/.test(s);
|
|
699
|
+
const splitCells = (s) => s.trim().replace(/^\||\|$/g, '').split('|').map(c => c.trim());
|
|
700
|
+
|
|
701
|
+
for (let i = 0; i < lines.length; i++) {
|
|
702
|
+
const line = lines[i];
|
|
703
|
+
|
|
668
704
|
if (!inCode && /^```(\w*)/.test(line)) {
|
|
669
705
|
inCode = true; codeLang = line.match(/^```(\w*)/)[1]; codeLines = [];
|
|
670
706
|
continue;
|
|
@@ -675,15 +711,31 @@
|
|
|
675
711
|
}
|
|
676
712
|
if (inCode) { codeLines.push(line); continue; }
|
|
677
713
|
|
|
714
|
+
// 表格
|
|
715
|
+
if (isTableRow(line) && i + 1 < lines.length && isTableSep(lines[i + 1])) {
|
|
716
|
+
const header = splitCells(line);
|
|
717
|
+
let tableHtml = '<table class="md-table"><thead><tr>' +
|
|
718
|
+
header.map(c => `<th>${fmtInline(escHtml(c))}</th>`).join('') +
|
|
719
|
+
'</tr></thead><tbody>';
|
|
720
|
+
i += 2; // 跳过表头和分隔行
|
|
721
|
+
while (i < lines.length && isTableRow(lines[i])) {
|
|
722
|
+
const cells = splitCells(lines[i]);
|
|
723
|
+
tableHtml += '<tr>' + cells.map(c => `<td>${fmtInline(escHtml(c))}</td>`).join('') + '</tr>';
|
|
724
|
+
i++;
|
|
725
|
+
}
|
|
726
|
+
tableHtml += '</tbody></table>';
|
|
727
|
+
html += tableHtml;
|
|
728
|
+
i--; // 回退一步让外层 for 循环正确递增
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
|
|
678
732
|
let l = escHtml(line);
|
|
679
733
|
// 标题
|
|
680
|
-
if (/^### /.test(l)) { html += `<h4>${l.slice(4)}</h4>`; continue; }
|
|
681
|
-
if (/^## /.test(l)) { html += `<h3>${l.slice(3)}</h3>`; continue; }
|
|
682
|
-
if (/^# /.test(l)) { html += `<h2>${l.slice(2)}</h2>`; continue; }
|
|
734
|
+
if (/^### /.test(l)) { html += `<h4>${fmtInline(l.slice(4))}</h4>`; continue; }
|
|
735
|
+
if (/^## /.test(l)) { html += `<h3>${fmtInline(l.slice(3))}</h3>`; continue; }
|
|
736
|
+
if (/^# /.test(l)) { html += `<h2>${fmtInline(l.slice(2))}</h2>`; continue; }
|
|
683
737
|
// 行内格式
|
|
684
|
-
l = l
|
|
685
|
-
l = l.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
|
686
|
-
l = l.replace(/`([^`]+)`/g, '<code>$1</code>');
|
|
738
|
+
l = fmtInline(l);
|
|
687
739
|
// 列表
|
|
688
740
|
if (/^- /.test(l)) { html += `<li>${l.slice(2)}</li>`; continue; }
|
|
689
741
|
if (/^\d+\. /.test(l)) { html += `<li>${l.replace(/^\d+\.\s*/, '')}</li>`; continue; }
|
|
@@ -1198,6 +1250,7 @@
|
|
|
1198
1250
|
|
|
1199
1251
|
claudeSession = isClaudeSession(session) || session.mode === 'agent';
|
|
1200
1252
|
updateShortcutBar();
|
|
1253
|
+
updatePlanButton();
|
|
1201
1254
|
|
|
1202
1255
|
// 更新输入框占位符
|
|
1203
1256
|
cmdInput.placeholder = session.mode === 'agent' ? '输入消息...' : '输入命令...';
|
|
@@ -1248,6 +1301,14 @@
|
|
|
1248
1301
|
setWorkState('idle');
|
|
1249
1302
|
} else if (msg.subtype === 'info' && msg.message) {
|
|
1250
1303
|
addStatusMessage(msg.message);
|
|
1304
|
+
// 同步计划模式状态到按钮
|
|
1305
|
+
if (msg.message.includes('进入计划模式')) {
|
|
1306
|
+
if (currentSession) currentSession.permissionMode = 'plan';
|
|
1307
|
+
updatePlanButton();
|
|
1308
|
+
} else if (msg.message.includes('退出计划模式')) {
|
|
1309
|
+
if (currentSession) currentSession.permissionMode = 'bypassPermissions';
|
|
1310
|
+
updatePlanButton();
|
|
1311
|
+
}
|
|
1251
1312
|
}
|
|
1252
1313
|
break;
|
|
1253
1314
|
case 'assistant':
|
|
@@ -2033,6 +2094,35 @@
|
|
|
2033
2094
|
let _slashCmd = null;
|
|
2034
2095
|
const _slashTitles = { '/plan': '计划模式', '/compact': '压缩上下文', '/rename': '重命名会话' };
|
|
2035
2096
|
const _slashHints = { '/plan': '输入计划描述...', '/compact': '输入压缩提示...', '/rename': '输入新名称...' };
|
|
2097
|
+
// 根据当前权限模式更新 "计划" 按钮 UI
|
|
2098
|
+
function updatePlanButton() {
|
|
2099
|
+
const btn = document.getElementById('btn-plan');
|
|
2100
|
+
if (!btn) return;
|
|
2101
|
+
const isPlan = currentSession?.permissionMode === 'plan';
|
|
2102
|
+
btn.textContent = isPlan ? '退出计划' : '计划';
|
|
2103
|
+
btn.style.color = isPlan ? '#f0883e' : '';
|
|
2104
|
+
btn.style.fontWeight = isPlan ? '600' : '';
|
|
2105
|
+
}
|
|
2106
|
+
window.togglePlanMode = function() {
|
|
2107
|
+
const isPlan = currentSession?.permissionMode === 'plan';
|
|
2108
|
+
if (!isController && canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID });
|
|
2109
|
+
if (isPlan) {
|
|
2110
|
+
// 直接切回 bypassPermissions,不走 /plan 命令(因为那要等 agent 响应)
|
|
2111
|
+
socket.emit('set-mode', { sessionId: SESSION_ID, mode: 'bypassPermissions' });
|
|
2112
|
+
if (currentSession) currentSession.permissionMode = 'bypassPermissions';
|
|
2113
|
+
updatePlanButton();
|
|
2114
|
+
addStatusMessage('已退出计划模式,恢复到自动执行');
|
|
2115
|
+
} else {
|
|
2116
|
+
// 进入计划:弹窗输入计划描述
|
|
2117
|
+
doSlashCmd('/plan');
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
socket.on('mode-changed', ({ sessionId, mode }) => {
|
|
2121
|
+
if (sessionId !== SESSION_ID) return;
|
|
2122
|
+
if (currentSession) currentSession.permissionMode = mode;
|
|
2123
|
+
updatePlanButton();
|
|
2124
|
+
});
|
|
2125
|
+
|
|
2036
2126
|
window.doSlashCmd = function(cmd) {
|
|
2037
2127
|
_slashCmd = cmd;
|
|
2038
2128
|
document.getElementById('slash-title').textContent = _slashTitles[cmd] || cmd;
|
|
@@ -2098,9 +2188,41 @@
|
|
|
2098
2188
|
}
|
|
2099
2189
|
} catch {}
|
|
2100
2190
|
}
|
|
2101
|
-
window.runSkill = function(name) {
|
|
2191
|
+
window.runSkill = function(name, skipPrompt) {
|
|
2192
|
+
// 直接运行(从弹窗确认后调用 skipPrompt=true)
|
|
2193
|
+
if (skipPrompt) {
|
|
2194
|
+
if (!isController && canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID });
|
|
2195
|
+
const cmd = '/' + name;
|
|
2196
|
+
socket.emit('agent:query', { prompt: cmd });
|
|
2197
|
+
addInputMessage(cmd);
|
|
2198
|
+
showThinking();
|
|
2199
|
+
return;
|
|
2200
|
+
}
|
|
2201
|
+
// 先弹窗让用户补充要求
|
|
2202
|
+
const skill = _customSkills.find(s => s.name === name);
|
|
2203
|
+
openSkillRunSheet(name, skill?.desc);
|
|
2204
|
+
};
|
|
2205
|
+
let _pendingSkillName = null;
|
|
2206
|
+
window.openSkillRunSheet = function(name, desc) {
|
|
2207
|
+
_pendingSkillName = name;
|
|
2208
|
+
const sheet = document.getElementById('skill-run-sheet');
|
|
2209
|
+
document.getElementById('skill-run-title').textContent = `/${name}`;
|
|
2210
|
+
document.getElementById('skill-run-desc').textContent = desc || '';
|
|
2211
|
+
document.getElementById('skill-run-input').value = '';
|
|
2212
|
+
sheet.classList.add('open');
|
|
2213
|
+
setTimeout(() => document.getElementById('skill-run-input').focus(), 100);
|
|
2214
|
+
};
|
|
2215
|
+
window.closeSkillRunSheet = function() {
|
|
2216
|
+
document.getElementById('skill-run-sheet').classList.remove('open');
|
|
2217
|
+
_pendingSkillName = null;
|
|
2218
|
+
};
|
|
2219
|
+
window.submitSkillRun = function() {
|
|
2220
|
+
if (!_pendingSkillName) return;
|
|
2221
|
+
const args = document.getElementById('skill-run-input').value.trim();
|
|
2222
|
+
const name = _pendingSkillName;
|
|
2223
|
+
closeSkillRunSheet();
|
|
2102
2224
|
if (!isController && canTakeControl()) socket.emit('take-control', { sessionId: SESSION_ID });
|
|
2103
|
-
const cmd =
|
|
2225
|
+
const cmd = args ? `/${name} ${args}` : `/${name}`;
|
|
2104
2226
|
socket.emit('agent:query', { prompt: cmd });
|
|
2105
2227
|
addInputMessage(cmd);
|
|
2106
2228
|
showThinking();
|