@wendongfly/myhi 1.0.118 → 1.0.120
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 +118 -18
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/chat.html
CHANGED
|
@@ -94,6 +94,25 @@
|
|
|
94
94
|
.btn-allow:hover { background: #2ea043; }
|
|
95
95
|
.btn-deny { background: #21262d; color: #f85149; border: 1px solid #30363d !important; }
|
|
96
96
|
|
|
97
|
+
/* 权限弹窗 modal */
|
|
98
|
+
#perm-modal { display: none; position: fixed; inset: 0; z-index: 90; align-items: flex-end; justify-content: center; }
|
|
99
|
+
#perm-modal.open { display: flex; }
|
|
100
|
+
#perm-modal-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,0.55); }
|
|
101
|
+
#perm-modal-box { position: relative; background: #161b22; border-radius: 16px 16px 0 0; width: 100%; max-width: 480px; padding: 1rem 1rem; padding-bottom: max(1rem, env(safe-area-inset-bottom)); z-index: 1; animation: slideUp 0.25s ease; border-top: 3px solid #d29922; }
|
|
102
|
+
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
|
|
103
|
+
#perm-modal-box .pm-icon { text-align: center; font-size: 1.6rem; margin-bottom: 0.4rem; }
|
|
104
|
+
#perm-modal-box .pm-title { text-align: center; font-size: 0.95rem; font-weight: 600; color: #d29922; margin-bottom: 0.6rem; }
|
|
105
|
+
#perm-modal-box .pm-tool { text-align: center; font-size: 0.78rem; color: #8b949e; margin-bottom: 0.3rem; }
|
|
106
|
+
#perm-modal-box .pm-detail { background: #0d1117; border: 1px solid #21262d; border-radius: 8px; padding: 0.6rem 0.75rem; font-family: 'SF Mono', 'Consolas', monospace; font-size: 0.78rem; line-height: 1.4; color: #e6edf3; white-space: pre-wrap; word-break: break-all; max-height: 200px; overflow-y: auto; margin-bottom: 0.75rem; }
|
|
107
|
+
#perm-modal-box .pm-actions { display: flex; gap: 0.5rem; }
|
|
108
|
+
#perm-modal-box .pm-actions button { flex: 1; padding: 0.6rem; border-radius: 10px; font-size: 0.88rem; font-weight: 600; cursor: pointer; border: none; transition: all 0.15s; }
|
|
109
|
+
#perm-modal-box .pm-actions button:active { transform: scale(0.96); }
|
|
110
|
+
#perm-modal-box .pm-btn-allow { background: #238636; color: #fff; }
|
|
111
|
+
#perm-modal-box .pm-btn-allow:hover { background: #2ea043; }
|
|
112
|
+
#perm-modal-box .pm-btn-deny { background: #21262d; color: #f85149; border: 1px solid #30363d; }
|
|
113
|
+
#perm-modal-box .pm-btn-deny:hover { background: #30363d; }
|
|
114
|
+
#perm-modal-box .pm-queue { text-align: center; font-size: 0.7rem; color: #8b949e; margin-top: 0.5rem; }
|
|
115
|
+
|
|
97
116
|
/* Diff 视图 */
|
|
98
117
|
.msg-diff { font-family: 'SF Mono', 'Consolas', monospace; font-size: 0.78rem; background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 0.5rem 0.6rem; overflow-x: auto; line-height: 1.35; }
|
|
99
118
|
.diff-add { color: #3fb950; background: rgba(46,160,67,0.1); }
|
|
@@ -226,12 +245,9 @@
|
|
|
226
245
|
<button class="top-btn" onclick="openSettings()" title="设置">
|
|
227
246
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 01-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
|
|
228
247
|
</button>
|
|
229
|
-
<button class="top-btn" onclick="goBack()" title="返回">
|
|
230
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
|
|
231
|
-
</button>
|
|
232
248
|
<button class="top-btn" onclick="showUsage()" title="用量" style="font-size:0.7rem;color:var(--muted)">用量</button>
|
|
233
|
-
<button class="top-btn"
|
|
234
|
-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9
|
|
249
|
+
<button class="top-btn" onclick="goBack()" title="返回">
|
|
250
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"/></svg>
|
|
235
251
|
</button>
|
|
236
252
|
</div>
|
|
237
253
|
|
|
@@ -393,6 +409,22 @@
|
|
|
393
409
|
</div>
|
|
394
410
|
</div>
|
|
395
411
|
|
|
412
|
+
<!-- 权限授权弹窗 -->
|
|
413
|
+
<div id="perm-modal">
|
|
414
|
+
<div id="perm-modal-backdrop"></div>
|
|
415
|
+
<div id="perm-modal-box">
|
|
416
|
+
<div class="pm-icon">🛡️</div>
|
|
417
|
+
<div class="pm-title" id="pm-title">请求权限</div>
|
|
418
|
+
<div class="pm-tool" id="pm-tool"></div>
|
|
419
|
+
<div class="pm-detail" id="pm-detail"></div>
|
|
420
|
+
<div class="pm-actions">
|
|
421
|
+
<button class="pm-btn-deny" id="pm-btn-deny">拒绝</button>
|
|
422
|
+
<button class="pm-btn-allow" id="pm-btn-allow">允许</button>
|
|
423
|
+
</div>
|
|
424
|
+
<div class="pm-queue" id="pm-queue" style="display:none"></div>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
|
|
396
428
|
<div id="status-overlay">连接中...</div>
|
|
397
429
|
|
|
398
430
|
<script type="module">
|
|
@@ -400,10 +432,7 @@
|
|
|
400
432
|
const ansi = new AnsiUp();
|
|
401
433
|
ansi.use_classes = false;
|
|
402
434
|
|
|
403
|
-
|
|
404
|
-
fetch('/api/me').then(r => r.json()).then(data => {
|
|
405
|
-
if (data.exclusive || data.hasUsers) document.getElementById('logout-btn').style.display = '';
|
|
406
|
-
}).catch(() => {});
|
|
435
|
+
fetch('/api/me').then(r => r.json()).catch(() => {});
|
|
407
436
|
window.showUsage = async () => {
|
|
408
437
|
try {
|
|
409
438
|
const res = await fetch('/api/usage');
|
|
@@ -453,13 +482,6 @@
|
|
|
453
482
|
document.body.appendChild(overlay);
|
|
454
483
|
} catch (err) { alert('获取用量失败: ' + err.message); }
|
|
455
484
|
};
|
|
456
|
-
window.doLogout = () => {
|
|
457
|
-
if (!confirm('确定退出登录?')) return;
|
|
458
|
-
fetch('/logout', { method: 'POST' }).finally(() => {
|
|
459
|
-
socket.disconnect();
|
|
460
|
-
location.href = '/login';
|
|
461
|
-
});
|
|
462
|
-
};
|
|
463
485
|
|
|
464
486
|
// ── 状态 ──────────────────────────────────────
|
|
465
487
|
const SESSION_ID = location.pathname.split('/').pop();
|
|
@@ -945,12 +967,83 @@
|
|
|
945
967
|
if (actions) actions.innerHTML = answer === 'y' ? '<span style="color:#3fb950">已允许</span>' : '<span style="color:#f85149">已拒绝</span>';
|
|
946
968
|
};
|
|
947
969
|
|
|
970
|
+
// ── 权限弹窗队列管理 ──────────────────────────────
|
|
971
|
+
const permQueue = []; // { reqId, toolName, detail }
|
|
972
|
+
let permModalOpen = false;
|
|
973
|
+
|
|
974
|
+
function showPermModal(item) {
|
|
975
|
+
const modal = document.getElementById('perm-modal');
|
|
976
|
+
document.getElementById('pm-title').textContent = `${item.toolName} 请求权限`;
|
|
977
|
+
document.getElementById('pm-tool').textContent = item.toolLabel || '';
|
|
978
|
+
document.getElementById('pm-detail').textContent = item.detail;
|
|
979
|
+
const queueEl = document.getElementById('pm-queue');
|
|
980
|
+
if (permQueue.length > 0) {
|
|
981
|
+
queueEl.textContent = `还有 ${permQueue.length} 个权限请求等待处理`;
|
|
982
|
+
queueEl.style.display = '';
|
|
983
|
+
} else {
|
|
984
|
+
queueEl.style.display = 'none';
|
|
985
|
+
}
|
|
986
|
+
// 绑定按钮
|
|
987
|
+
document.getElementById('pm-btn-allow').onclick = () => respondPermModal(item.reqId, true);
|
|
988
|
+
document.getElementById('pm-btn-deny').onclick = () => respondPermModal(item.reqId, false);
|
|
989
|
+
modal.classList.add('open');
|
|
990
|
+
permModalOpen = true;
|
|
991
|
+
// 振动提醒(移动端)
|
|
992
|
+
if (navigator.vibrate) navigator.vibrate(100);
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
function closePermModal() {
|
|
996
|
+
document.getElementById('perm-modal').classList.remove('open');
|
|
997
|
+
permModalOpen = false;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function respondPermModal(requestId, allow) {
|
|
1001
|
+
if (!isController) { addStatusMessage('你没有控制权,无法操作'); return; }
|
|
1002
|
+
socket.emit('agent:permission', { requestId, allow });
|
|
1003
|
+
// 更新内联卡片
|
|
1004
|
+
const inlineActions = document.querySelector(`.perm-actions[data-reqid="${requestId}"]`);
|
|
1005
|
+
if (inlineActions) inlineActions.innerHTML = allow ? '<span style="color:#3fb950">✓ 已允许</span>' : '<span style="color:#f85149">✗ 已拒绝</span>';
|
|
1006
|
+
closePermModal();
|
|
1007
|
+
setWorkState('working');
|
|
1008
|
+
// 处理队列中的下一个
|
|
1009
|
+
if (permQueue.length > 0) {
|
|
1010
|
+
const next = permQueue.shift();
|
|
1011
|
+
setTimeout(() => showPermModal(next), 200);
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
function enqueuePermission(reqId, toolName, detail, toolLabel) {
|
|
1016
|
+
const item = { reqId, toolName, detail, toolLabel };
|
|
1017
|
+
if (!permModalOpen) {
|
|
1018
|
+
showPermModal(item);
|
|
1019
|
+
} else {
|
|
1020
|
+
permQueue.push(item);
|
|
1021
|
+
// 更新队列提示
|
|
1022
|
+
const queueEl = document.getElementById('pm-queue');
|
|
1023
|
+
queueEl.textContent = `还有 ${permQueue.length} 个权限请求等待处理`;
|
|
1024
|
+
queueEl.style.display = '';
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// backdrop 点击不关闭弹窗(防止误触),但可以拒绝
|
|
1029
|
+
document.getElementById('perm-modal-backdrop').addEventListener('click', () => {
|
|
1030
|
+
// 不自动关闭,必须明确选择
|
|
1031
|
+
});
|
|
1032
|
+
|
|
948
1033
|
window.respondAgentPermission = function(requestId, allow, btn) {
|
|
949
1034
|
if (!isController) { addStatusMessage('你没有控制权,无法操作'); return; }
|
|
950
1035
|
socket.emit('agent:permission', { requestId, allow });
|
|
951
1036
|
const actions = btn.closest('.perm-actions');
|
|
952
|
-
if (actions) actions.innerHTML = allow ? '<span style="color:#3fb950"
|
|
1037
|
+
if (actions) actions.innerHTML = allow ? '<span style="color:#3fb950">✓ 已允许</span>' : '<span style="color:#f85149">✗ 已拒绝</span>';
|
|
953
1038
|
setWorkState('working');
|
|
1039
|
+
// 如果弹窗正在显示同一个请求,也关闭它
|
|
1040
|
+
if (permModalOpen) {
|
|
1041
|
+
closePermModal();
|
|
1042
|
+
if (permQueue.length > 0) {
|
|
1043
|
+
const next = permQueue.shift();
|
|
1044
|
+
setTimeout(() => showPermModal(next), 200);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
954
1047
|
};
|
|
955
1048
|
|
|
956
1049
|
// ── 输出处理 ──────────────────────────────────
|
|
@@ -1176,10 +1269,15 @@
|
|
|
1176
1269
|
const toolName = msg.request.tool_name || '未知工具';
|
|
1177
1270
|
const input = msg.request.input || {};
|
|
1178
1271
|
const detail = toolName === 'Bash' ? (input.command || JSON.stringify(input))
|
|
1179
|
-
: toolName === 'Edit' ? `${input.file_path || ''}`
|
|
1272
|
+
: toolName === 'Edit' ? `${input.file_path || ''}\n${input.old_string ? '替换: ' + input.old_string.slice(0, 120) : ''}`
|
|
1180
1273
|
: toolName === 'Write' ? `${input.file_path || ''}`
|
|
1274
|
+
: toolName === 'Read' ? `${input.file_path || ''}`
|
|
1181
1275
|
: JSON.stringify(input, null, 2);
|
|
1182
1276
|
const reqId = msg.request_id || msg.request?.request_id || msg.uuid;
|
|
1277
|
+
// 工具类型标签
|
|
1278
|
+
const toolLabels = { Bash: '执行命令', Edit: '编辑文件', Write: '写入文件', Read: '读取文件', Glob: '搜索文件', Grep: '搜索内容' };
|
|
1279
|
+
const toolLabel = toolLabels[toolName] || toolName;
|
|
1280
|
+
// 内联卡片
|
|
1183
1281
|
const el = document.createElement('div');
|
|
1184
1282
|
el.className = 'msg msg-permission';
|
|
1185
1283
|
el.innerHTML = `<div class="perm-title">${escHtml(toolName)} 请求权限</div><div class="perm-detail">${escHtml(detail)}</div>
|
|
@@ -1191,6 +1289,8 @@
|
|
|
1191
1289
|
trimMessages();
|
|
1192
1290
|
scrollToBottom();
|
|
1193
1291
|
setWorkState('waiting');
|
|
1292
|
+
// 弹窗授权
|
|
1293
|
+
enqueuePermission(reqId, toolName, detail, toolLabel);
|
|
1194
1294
|
}
|
|
1195
1295
|
break;
|
|
1196
1296
|
case 'result':
|
package/dist/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"1.0.
|
|
1
|
+
{"type":"module","version":"1.0.120"}
|
package/package.json
CHANGED