@wendongfly/myhi 1.0.118 → 1.0.119

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
@@ -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); }
@@ -230,9 +249,6 @@
230
249
  <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
250
  </button>
232
251
  <button class="top-btn" onclick="showUsage()" title="用量" style="font-size:0.7rem;color:var(--muted)">用量</button>
233
- <button class="top-btn" id="logout-btn" onclick="doLogout()" title="退出" style="display:none;color:#f0883e">
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 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
235
- </button>
236
252
  </div>
237
253
 
238
254
  <div id="status-bar">
@@ -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">&#x1F6E1;&#xFE0F;</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">
@@ -945,12 +977,83 @@
945
977
  if (actions) actions.innerHTML = answer === 'y' ? '<span style="color:#3fb950">已允许</span>' : '<span style="color:#f85149">已拒绝</span>';
946
978
  };
947
979
 
980
+ // ── 权限弹窗队列管理 ──────────────────────────────
981
+ const permQueue = []; // { reqId, toolName, detail }
982
+ let permModalOpen = false;
983
+
984
+ function showPermModal(item) {
985
+ const modal = document.getElementById('perm-modal');
986
+ document.getElementById('pm-title').textContent = `${item.toolName} 请求权限`;
987
+ document.getElementById('pm-tool').textContent = item.toolLabel || '';
988
+ document.getElementById('pm-detail').textContent = item.detail;
989
+ const queueEl = document.getElementById('pm-queue');
990
+ if (permQueue.length > 0) {
991
+ queueEl.textContent = `还有 ${permQueue.length} 个权限请求等待处理`;
992
+ queueEl.style.display = '';
993
+ } else {
994
+ queueEl.style.display = 'none';
995
+ }
996
+ // 绑定按钮
997
+ document.getElementById('pm-btn-allow').onclick = () => respondPermModal(item.reqId, true);
998
+ document.getElementById('pm-btn-deny').onclick = () => respondPermModal(item.reqId, false);
999
+ modal.classList.add('open');
1000
+ permModalOpen = true;
1001
+ // 振动提醒(移动端)
1002
+ if (navigator.vibrate) navigator.vibrate(100);
1003
+ }
1004
+
1005
+ function closePermModal() {
1006
+ document.getElementById('perm-modal').classList.remove('open');
1007
+ permModalOpen = false;
1008
+ }
1009
+
1010
+ function respondPermModal(requestId, allow) {
1011
+ if (!isController) { addStatusMessage('你没有控制权,无法操作'); return; }
1012
+ socket.emit('agent:permission', { requestId, allow });
1013
+ // 更新内联卡片
1014
+ const inlineActions = document.querySelector(`.perm-actions[data-reqid="${requestId}"]`);
1015
+ if (inlineActions) inlineActions.innerHTML = allow ? '<span style="color:#3fb950">✓ 已允许</span>' : '<span style="color:#f85149">✗ 已拒绝</span>';
1016
+ closePermModal();
1017
+ setWorkState('working');
1018
+ // 处理队列中的下一个
1019
+ if (permQueue.length > 0) {
1020
+ const next = permQueue.shift();
1021
+ setTimeout(() => showPermModal(next), 200);
1022
+ }
1023
+ }
1024
+
1025
+ function enqueuePermission(reqId, toolName, detail, toolLabel) {
1026
+ const item = { reqId, toolName, detail, toolLabel };
1027
+ if (!permModalOpen) {
1028
+ showPermModal(item);
1029
+ } else {
1030
+ permQueue.push(item);
1031
+ // 更新队列提示
1032
+ const queueEl = document.getElementById('pm-queue');
1033
+ queueEl.textContent = `还有 ${permQueue.length} 个权限请求等待处理`;
1034
+ queueEl.style.display = '';
1035
+ }
1036
+ }
1037
+
1038
+ // backdrop 点击不关闭弹窗(防止误触),但可以拒绝
1039
+ document.getElementById('perm-modal-backdrop').addEventListener('click', () => {
1040
+ // 不自动关闭,必须明确选择
1041
+ });
1042
+
948
1043
  window.respondAgentPermission = function(requestId, allow, btn) {
949
1044
  if (!isController) { addStatusMessage('你没有控制权,无法操作'); return; }
950
1045
  socket.emit('agent:permission', { requestId, allow });
951
1046
  const actions = btn.closest('.perm-actions');
952
- if (actions) actions.innerHTML = allow ? '<span style="color:#3fb950">已允许</span>' : '<span style="color:#f85149">已拒绝</span>';
1047
+ if (actions) actions.innerHTML = allow ? '<span style="color:#3fb950">✓ 已允许</span>' : '<span style="color:#f85149">✗ 已拒绝</span>';
953
1048
  setWorkState('working');
1049
+ // 如果弹窗正在显示同一个请求,也关闭它
1050
+ if (permModalOpen) {
1051
+ closePermModal();
1052
+ if (permQueue.length > 0) {
1053
+ const next = permQueue.shift();
1054
+ setTimeout(() => showPermModal(next), 200);
1055
+ }
1056
+ }
954
1057
  };
955
1058
 
956
1059
  // ── 输出处理 ──────────────────────────────────
@@ -1176,10 +1279,15 @@
1176
1279
  const toolName = msg.request.tool_name || '未知工具';
1177
1280
  const input = msg.request.input || {};
1178
1281
  const detail = toolName === 'Bash' ? (input.command || JSON.stringify(input))
1179
- : toolName === 'Edit' ? `${input.file_path || ''}`
1282
+ : toolName === 'Edit' ? `${input.file_path || ''}\n${input.old_string ? '替换: ' + input.old_string.slice(0, 120) : ''}`
1180
1283
  : toolName === 'Write' ? `${input.file_path || ''}`
1284
+ : toolName === 'Read' ? `${input.file_path || ''}`
1181
1285
  : JSON.stringify(input, null, 2);
1182
1286
  const reqId = msg.request_id || msg.request?.request_id || msg.uuid;
1287
+ // 工具类型标签
1288
+ const toolLabels = { Bash: '执行命令', Edit: '编辑文件', Write: '写入文件', Read: '读取文件', Glob: '搜索文件', Grep: '搜索内容' };
1289
+ const toolLabel = toolLabels[toolName] || toolName;
1290
+ // 内联卡片
1183
1291
  const el = document.createElement('div');
1184
1292
  el.className = 'msg msg-permission';
1185
1293
  el.innerHTML = `<div class="perm-title">${escHtml(toolName)} 请求权限</div><div class="perm-detail">${escHtml(detail)}</div>
@@ -1191,6 +1299,8 @@
1191
1299
  trimMessages();
1192
1300
  scrollToBottom();
1193
1301
  setWorkState('waiting');
1302
+ // 弹窗授权
1303
+ enqueuePermission(reqId, toolName, detail, toolLabel);
1194
1304
  }
1195
1305
  break;
1196
1306
  case 'result':
package/dist/package.json CHANGED
@@ -1 +1 @@
1
- {"type":"module","version":"1.0.118"}
1
+ {"type":"module","version":"1.0.119"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wendongfly/myhi",
3
- "version": "1.0.118",
3
+ "version": "1.0.119",
4
4
  "description": "Web-based terminal sharing with chat UI — control your terminal from phone via LAN/Tailscale",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",