@wendongfly/myhi 1.3.109 → 1.3.110

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
@@ -331,6 +331,7 @@
331
331
  <body>
332
332
 
333
333
  <div id="top-bar">
334
+ <button class="top-btn" onclick="location.href='/grid'" title="分屏工作台(多任务并排)" style="font-size:1.05rem;padding:0 0.35rem;color:var(--blue2)">▦</button>
334
335
  <div id="title-group">
335
336
  <div id="session-title">加载中...</div>
336
337
  <div id="session-cwd"></div>
@@ -341,7 +342,6 @@
341
342
  <button class="top-btn" onclick="showUsage()" title="用量" style="font-size:0.7rem;color:var(--muted)">用量</button>
342
343
  <button class="top-btn" onclick="openFilePanel()" title="文件" style="font-size:0.7rem;color:var(--muted)">文件</button>
343
344
  <button class="top-btn" onclick="openSwitchSheet()" title="切换会话" style="font-size:0.7rem;color:var(--muted)">切换</button>
344
- <button class="top-btn" onclick="location.href='/grid'" title="分屏工作台(多任务并排)" style="font-size:0.7rem;color:var(--muted)">▦ 分屏</button>
345
345
  <button class="top-btn" onclick="goBack()" title="返回">
346
346
  <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>
347
347
  </button>
@@ -365,11 +365,21 @@
365
365
  <span class="img-info">已添加图片,输入文字后发送</span>
366
366
  <button class="img-remove" onclick="clearPendingImage()" title="移除图片">&times;</button>
367
367
  </div>
368
+ <div id="file-preview" style="display:none;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-bottom:1px solid var(--surface2);background:var(--surface)">
369
+ <span style="font-size:1.1rem;flex-shrink:0">📎</span>
370
+ <span id="file-preview-name" style="flex:1;font-size:0.78rem;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap"></span>
371
+ <span style="font-size:0.66rem;color:var(--muted);flex-shrink:0">临时·仅本会话分析</span>
372
+ <button class="img-remove" onclick="clearPendingFile()" title="移除文件">&times;</button>
373
+ </div>
368
374
  <textarea id="cmd-input" rows="1" placeholder="输入消息..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></textarea>
369
375
  <div id="input-toolbar">
370
376
  <button class="tb-btn" id="btn-photo" onclick="openCamera()" title="拍照">
371
377
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/></svg>
372
378
  </button>
379
+ <button class="tb-btn" id="btn-file" onclick="document.getElementById('file-input').click()" title="上传临时文件让 AI 分析(不进任务文件树,仅本会话)">
380
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>
381
+ </button>
382
+ <input type="file" id="file-input" style="display:none" onchange="uploadTempFile(this.files[0]); this.value='';">
373
383
  <span id="enter-hint" style="display:none;font-size:0.68rem;color:var(--muted);white-space:nowrap;align-self:center;margin-left:0.15rem"></span>
374
384
  <div class="spacer"></div>
375
385
  <button class="tb-btn" id="voice-btn" onclick="openVaSheet()" title="语音输入 / 需求助手">
@@ -2036,11 +2046,44 @@
2036
2046
  cmdInput.focus();
2037
2047
  }
2038
2048
 
2049
+ // ── 待发送临时文件(存 ~/.myhi/uploads/,**不进项目文件树**,仅本会话即时分析)──
2050
+ let _pendingFile = null; // { path, name }
2051
+ window.clearPendingFile = function() {
2052
+ _pendingFile = null;
2053
+ const fp = document.getElementById('file-preview');
2054
+ if (fp) fp.style.display = 'none';
2055
+ };
2056
+ window.uploadTempFile = async function(file) {
2057
+ if (!file) return;
2058
+ const fp = document.getElementById('file-preview');
2059
+ const nameEl = document.getElementById('file-preview-name');
2060
+ if (nameEl) nameEl.textContent = '上传中… ' + file.name;
2061
+ if (fp) fp.style.display = 'flex';
2062
+ try {
2063
+ const form = new FormData();
2064
+ form.append('file', file, file.name);
2065
+ const r = await fetch(`/upload-file?sessionId=${SESSION_ID}`, { method: 'POST', body: form });
2066
+ const d = await r.json();
2067
+ if (d.path) {
2068
+ _pendingFile = { path: d.path, name: d.name || file.name };
2069
+ if (nameEl) nameEl.textContent = _pendingFile.name;
2070
+ cmdInput.placeholder = '输入分析要求后发送(可留空)…';
2071
+ cmdInput.focus();
2072
+ } else {
2073
+ if (nameEl) nameEl.textContent = '上传失败: ' + (d.error || '未知');
2074
+ _pendingFile = null;
2075
+ }
2076
+ } catch (e) {
2077
+ if (nameEl) nameEl.textContent = '上传出错: ' + e.message;
2078
+ _pendingFile = null;
2079
+ }
2080
+ };
2081
+
2039
2082
  // ── 输入处理 ──────────────────────────────────
2040
2083
  window.sendCommand = sendCommand;
2041
2084
  function sendCommand() {
2042
2085
  const text = cmdInput.value.trim();
2043
- if (!text && !_pendingImage) return;
2086
+ if (!text && !_pendingImage && !_pendingFile) return;
2044
2087
 
2045
2088
  if (!isController) {
2046
2089
  if (canTakeControl()) { socket.emit('take-control', { sessionId: SESSION_ID }); }
@@ -2049,29 +2092,37 @@
2049
2092
  endStream();
2050
2093
 
2051
2094
  const imgPath = _pendingImage?.path || null;
2095
+ const filePath = _pendingFile?.path || null;
2096
+ const fileName = _pendingFile?.name || '';
2052
2097
  const userText = text;
2053
- const displayText = imgPath ? `📷 ${userText || '分析图片'}` : text;
2098
+ const displayText = imgPath ? `📷 ${userText || '分析图片'}`
2099
+ : filePath ? `📎 ${fileName}${userText ? ' ' + userText : ''}`
2100
+ : text;
2054
2101
 
2055
2102
  addInputMessage(displayText);
2056
2103
 
2057
2104
  if (currentSession?.mode === 'agent') {
2058
2105
  const prompt = imgPath
2059
2106
  ? `用户上传了一张图片,路径是 ${imgPath},请用 Read 工具读取这张图片。用户的要求是:${userText || '描述图片内容'}`
2107
+ : filePath
2108
+ ? `用户上传了一个临时文件用于本次分析(不在项目文件树里),路径是 ${filePath}(原文件名 ${fileName}),请用合适的工具(如 Read)读取并分析它。用户的要求是:${userText || '分析这个文件'}`
2060
2109
  : text;
2061
2110
  socket.emit('agent:query', { prompt });
2062
2111
  showThinking();
2063
2112
  } else {
2064
- const input = imgPath
2065
- ? (userText ? `${userText} ${imgPath}` : imgPath)
2113
+ const attach = imgPath || filePath;
2114
+ const input = attach
2115
+ ? (userText ? `${userText} ${attach}` : attach)
2066
2116
  : text;
2067
2117
  socket.emit('input', input + '\r');
2068
2118
  }
2069
- cmdHistory.unshift(imgPath ? `[图片] ${userText}` : text);
2119
+ cmdHistory.unshift(imgPath ? `[图片] ${userText}` : filePath ? `[文件] ${fileName} ${userText}` : text);
2070
2120
  if (cmdHistory.length > 100) cmdHistory.pop();
2071
2121
  historyIdx = -1;
2072
2122
  cmdInput.value = '';
2073
2123
  cmdInput.style.height = 'auto';
2074
2124
  clearPendingImage();
2125
+ clearPendingFile();
2075
2126
  cmdInput.focus();
2076
2127
  }
2077
2128
 
package/dist/grid.html CHANGED
@@ -5,6 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
6
6
  <meta name="theme-color" content="#0d1117">
7
7
  <title>myhi 分屏</title>
8
+ <script src="/sio-client/socket.io.min.js"></script>
8
9
  <script>
9
10
  (function(){try{
10
11
  var t=localStorage.getItem('myhi_theme')||'dark';
@@ -65,7 +66,8 @@
65
66
  </div>
66
67
  <span class="spacer"></span>
67
68
  <button class="bar-btn" onclick="refreshSessions(true)" title="刷新任务列表">↻</button>
68
- <button class="bar-btn" style="border-color:var(--blue2);color:var(--blue)" onclick="addPane('')">+ 添加任务</button>
69
+ <button class="bar-btn" onclick="addPane('')" title="加一个空窗格,从下拉选已有任务">+ 窗格</button>
70
+ <button class="bar-btn" style="border-color:var(--green);color:var(--green)" onclick="newTask()" title="新建一个任务并放进新窗格">🆕 新建任务</button>
69
71
  </div>
70
72
  <div id="grid"></div>
71
73
  <div id="empty-hint" style="display:none">点「+ 添加任务」把多个任务并排看。<br>拉宽窗口自动多几格,或用上方按钮锁定布局。</div>
@@ -190,6 +192,20 @@
190
192
  }
191
193
  }
192
194
 
195
+ // ── 新建任务(走 socket create-agent,和首页一致)──
196
+ const socket = io();
197
+ window.newTask = function() {
198
+ const title = (prompt('新任务名称:') || '').trim();
199
+ if (!title) return;
200
+ socket.emit('create-agent', { title }, (res) => {
201
+ if (res && res.ok && res.session) {
202
+ refreshSessions(true).then(() => addPane(res.session.id));
203
+ } else {
204
+ alert('创建失败:' + ((res && res.error) || '未知错误'));
205
+ }
206
+ });
207
+ };
208
+
193
209
  // ── 初始化 ──
194
210
  (async function init() {
195
211
  await refreshSessions(false);