myagent-ai 1.23.33 → 1.23.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.23.33",
3
+ "version": "1.23.34",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
package/web/api_server.py CHANGED
@@ -7807,8 +7807,10 @@ window.addEventListener('beforeunload', function() {{
7807
7807
  # 构建最终消息(用户原文不包含任何注入内容)
7808
7808
  agent_content = content
7809
7809
 
7810
+ # [v1.23.34] 群聊场景直接调用 _try_model_chain_inner(绕过全局锁)
7811
+ # 全局锁 _model_chain_lock 在并行场景下会导致死锁/阻塞
7810
7812
  if model_chain and self.core.llm:
7811
- response = await self._try_model_chain(
7813
+ response = await self._try_model_chain_inner(
7812
7814
  model_chain, agent_content, session_id,
7813
7815
  agent_path=agent_path, agent_system_prompt=agent_system_prompt,
7814
7816
  )
@@ -7841,26 +7843,21 @@ window.addEventListener('beforeunload', function() {{
7841
7843
  "response": f"处理失败: {str(e)}",
7842
7844
  }
7843
7845
 
7844
- # 并行调用目标成员agent
7845
- tasks = [process_agent_member(m) for m in target_members]
7846
- try:
7847
- gather_results = await asyncio.gather(*tasks, return_exceptions=True)
7848
- except Exception as e:
7849
- logger.error(f"群消息广播异常: {e}")
7850
- tp.update_task_status(task_id, "failed", last_message=f"广播异常: {str(e)}")
7851
- return web.json_response({"error": f"群消息广播异常: {str(e)}"}, status=500)
7852
-
7853
- # 处理异常结果并按原始成员顺序排序
7846
+ # [v1.23.34] 串行调用目标成员agent(避免并行时 LLM 全局状态互相覆盖导致卡死)
7847
+ # 原因: _try_model_chain_inner 会修改 self.core.llm provider/model/api_key 等全局属性
7848
+ # 并行执行会导致 Agent 之间互相覆盖模型配置,甚至死锁
7854
7849
  raw_responses = []
7855
- for r in gather_results:
7856
- if isinstance(r, Exception):
7850
+ for member in target_members:
7851
+ try:
7852
+ result = await process_agent_member(member)
7853
+ raw_responses.append(result)
7854
+ except Exception as e:
7855
+ logger.error(f"群消息处理异常 ({member.agent_path}): {e}")
7857
7856
  raw_responses.append({
7858
- "ok": False, "agent_path": "unknown",
7859
- "name": "unknown", "avatar": "❌",
7860
- "response": f"异常: {str(r)}",
7857
+ "ok": False, "agent_path": member.agent_path,
7858
+ "name": member.agent_path, "avatar": "❌",
7859
+ "response": f"异常: {str(e)}",
7861
7860
  })
7862
- else:
7863
- raw_responses.append(r)
7864
7861
 
7865
7862
  # Sort by original member order to ensure deterministic message ordering
7866
7863
  final_responses = sorted(
@@ -1797,6 +1797,7 @@ input,textarea,select{font:inherit}
1797
1797
  border:1px solid var(--border-light);border-bottom-left-radius:4px;
1798
1798
  border-left:3px solid var(--accent);
1799
1799
  overflow-wrap:break-word;overflow:hidden;position:relative;
1800
+ user-select:text;-webkit-user-select:text;
1800
1801
  }
1801
1802
  .group-msg-bubble p{margin-bottom:8px}
1802
1803
  .group-msg-bubble p:last-child{margin-bottom:0}
@@ -328,6 +328,14 @@ const StatePersistence = {
328
328
  if (savedSessionId) {
329
329
  state._pendingSessionRestore = savedSessionId;
330
330
  }
331
+ // [v1.23.34] 恢复群聊状态
332
+ var savedView = StatePersistence.load('currentView', 'chat');
333
+ var savedGroupId = StatePersistence.load('currentGroupId', null);
334
+ if (savedView === 'group' && savedGroupId) {
335
+ currentView = 'group';
336
+ currentGroupId = savedGroupId;
337
+ state._pendingGroupRestore = savedGroupId;
338
+ }
331
339
  },
332
340
  /** 标记 setup 已完成(避免每次刷新弹出向导) */
333
341
  markSetupDone() { StatePersistence.save('setupDone', true); },
@@ -465,6 +473,14 @@ async function initChat() {
465
473
  }
466
474
  // 如果 agent 一致,loadSessions() 内部已通过 _pendingSessionRestore 自动处理了
467
475
  }
476
+
477
+ // [v1.23.34] 恢复群聊视图(在所有初始化完成后)
478
+ if (state._pendingGroupRestore && typeof selectGroup === 'function') {
479
+ var _gid = state._pendingGroupRestore;
480
+ state._pendingGroupRestore = null;
481
+ // 等待 fetchGroups 完成(initChat 中已调用),延迟恢复
482
+ setTimeout(function() { selectGroup(_gid); }, 300);
483
+ }
468
484
  }
469
485
 
470
486
  // Run init: if DOMContentLoaded already fired (dynamic script load), run immediately
@@ -138,6 +138,11 @@ async function selectGroup(gid) {
138
138
  }
139
139
  currentView = 'group';
140
140
  currentGroupId = gid;
141
+ // [v1.23.34] 持久化群聊状态,刷新页面后恢复
142
+ if (typeof StatePersistence !== 'undefined') {
143
+ StatePersistence.save('currentView', 'group');
144
+ StatePersistence.save('currentGroupId', gid);
145
+ }
141
146
 
142
147
  // Update sidebar
143
148
  renderSessions();
@@ -194,6 +199,11 @@ function exitGroupChat() {
194
199
  currentView = 'chat';
195
200
  currentGroupId = null;
196
201
  groupMessages = [];
202
+ // [v1.23.34] 清除持久化的群聊状态
203
+ if (typeof StatePersistence !== 'undefined') {
204
+ StatePersistence.save('currentView', 'chat');
205
+ StatePersistence.remove('currentGroupId');
206
+ }
197
207
  // 清空残留的聊天状态,避免切回个人聊天时显示群聊消息
198
208
  state.messages = [];
199
209
  state.activeSessionId = null;
@@ -267,8 +277,10 @@ function _renderGroupMessagesInner() {
267
277
  var agentEmoji = msg.agent_emoji || msg.sender_avatar || msg.avatar || '🤖';
268
278
  var agentColor = msg.agent_color || msg.color || 'var(--accent)';
269
279
  var agentRole = msg.agent_role || msg.role_detail || '';
280
+ var agentPath = msg.agent || '';
281
+ var _clickAvatar = agentPath ? ' onclick="showAgentProfile(\'' + escapeHtml(agentPath) + '\')" style="background:' + agentColor + ';color:#fff;cursor:pointer" title="点击查看简介"' : ' style="background:' + agentColor + ';color:#fff"';
270
282
  html += '<div class="group-msg-row">'
271
- + '<div class="group-msg-avatar" style="background:' + agentColor + ';color:#fff">' + agentEmoji + '</div>'
283
+ + '<div class="group-msg-avatar"' + _clickAvatar + '>' + agentEmoji + '</div>'
272
284
  + '<div>'
273
285
  + '<div class="group-msg-name">' + escapeHtml(agentName)
274
286
  + (agentRole ? ' <span class="role-badge">' + escapeHtml(agentRole) + '</span>' : '')
@@ -283,8 +295,10 @@ function _renderGroupMessagesInner() {
283
295
  var rName = r.agent_name || r.sender_name || r.name || r.agent || 'Agent';
284
296
  var rEmoji = r.agent_emoji || r.sender_avatar || r.avatar || '🤖';
285
297
  var rColor = r.agent_color || r.color || 'var(--accent)';
298
+ var rPath = r.agent_path || '';
299
+ var _rClickAvatar = rPath ? ' onclick="showAgentProfile(\'' + escapeHtml(rPath) + '\')" style="background:' + rColor + ';color:#fff;cursor:pointer" title="点击查看简介"' : ' style="background:' + rColor + ';color:#fff"';
286
300
  html += '<div class="group-msg-row">'
287
- + '<div class="group-msg-avatar" style="background:' + rColor + ';color:#fff">' + rEmoji + '</div>'
301
+ + '<div class="group-msg-avatar"' + _rClickAvatar + '>' + rEmoji + '</div>'
288
302
  + '<div>'
289
303
  + '<div class="group-msg-name">' + escapeHtml(rName) + '</div>'
290
304
  + '<div class="group-msg-bubble" style="border-left-color:' + rColor + '">' + renderMarkdown(r.content || r.response || '') + '</div>'
@@ -294,6 +308,17 @@ function _renderGroupMessagesInner() {
294
308
  }
295
309
 
296
310
  container.innerHTML = html;
311
+ // [v1.23.34] 为所有群聊气泡添加双击复制功能
312
+ container.querySelectorAll('.group-msg-bubble').forEach(function(bubble) {
313
+ bubble.addEventListener('dblclick', function() {
314
+ var text = bubble.innerText || bubble.textContent || '';
315
+ if (text) {
316
+ navigator.clipboard.writeText(text).then(function() {
317
+ if (typeof toast === 'function') toast('已复制消息', 'success');
318
+ }).catch(function() {});
319
+ }
320
+ });
321
+ });
297
322
  scrollToBottom();
298
323
  }
299
324
 
@@ -798,3 +823,33 @@ async function sendGroupChat() {
798
823
  input.focus();
799
824
  }
800
825
  }
826
+
827
+ // ══════════════════════════════════════════════════════
828
+ // ── Agent Profile Popup (点击头像显示简介) ──
829
+ // ══════════════════════════════════════════════════════
830
+
831
+ function showAgentProfile(agentPath) {
832
+ var agent = (state.agentsFlat || []).find(function(a) { return a.path === agentPath; });
833
+ if (!agent) {
834
+ if (typeof toast === 'function') toast('未找到 Agent 信息', 'error');
835
+ return;
836
+ }
837
+ var name = agent.name || agentPath;
838
+ var emoji = agent.avatar_emoji || '🤖';
839
+ var color = agent.avatar_color || getAgentGradient(name);
840
+ var desc = agent.description || '暂无描述';
841
+ var tools = agent.tools || [];
842
+ var toolsStr = tools.length > 0 ? tools.join(', ') : '默认工具集';
843
+
844
+ var container = document.getElementById('groupModalContainer');
845
+ container.innerHTML = '<div class="modal-overlay" onclick="if(event.target===this)closeGroupModal()"><div class="group-modal" style="max-width:380px">'
846
+ + '<div style="display:flex;align-items:center;gap:14px;margin-bottom:16px">'
847
+ + '<div class="group-msg-avatar" style="background:' + color + ';color:#fff;width:48px;height:48px;border-radius:12px;font-size:22px">' + emoji + '</div>'
848
+ + '<div><div style="font-size:18px;font-weight:700;color:var(--text)">' + escapeHtml(name) + '</div>'
849
+ + '<div style="font-size:12px;color:var(--text3)">' + escapeHtml(agentPath) + '</div></div></div>'
850
+ + '<div style="font-size:14px;color:var(--text2);line-height:1.6;margin-bottom:14px;padding:12px;background:var(--bg);border-radius:var(--radius-sm);border:1px solid var(--border-light)">' + escapeHtml(desc) + '</div>'
851
+ + (tools.length > 0 ? '<div style="font-size:12px;color:var(--text3);margin-bottom:14px"><span style="font-weight:600">工具:</span> ' + escapeHtml(toolsStr) + '</div>' : '')
852
+ + '<div class="agent-modal-actions">'
853
+ + '<button class="agent-modal-btn agent-modal-btn-cancel" onclick="closeGroupModal()">关闭</button>'
854
+ + '</div></div></div>';
855
+ }