myagent-ai 1.24.0 → 1.24.2

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.
@@ -716,6 +716,10 @@ class MainAgent(BaseAgent):
716
716
  _attachment_meta["images"] = context.metadata["user_image_files"]
717
717
  if context.metadata.get("user_file_files"):
718
718
  _attachment_meta["files"] = context.metadata["user_file_files"]
719
+ # [v1.24.1] 保存 agent_path 到用户消息 metadata,用于会话列表按 agent 筛选
720
+ _agent_path = context.metadata.get("agent_override_path", "")
721
+ if _agent_path:
722
+ _attachment_meta["agent_path"] = _agent_path
719
723
  self.memory.add_session(
720
724
  session_id=context.session_id,
721
725
  role="user",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.24.0",
3
+ "version": "1.24.2",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
package/start.js CHANGED
@@ -641,7 +641,13 @@ function cmdUninstall() {
641
641
  if (IS_WIN) {
642
642
  execSync('taskkill /F /IM python.exe /FI "WINDOWTITLE eq myagent*" 2>nul', { encoding: "utf8", timeout: 5000 });
643
643
  } else {
644
- execSync("pkill -f 'myagent|main.py' 2>/dev/null", { encoding: "utf8", timeout: 10000 });
644
+ // 排除当前进程 PID,避免 pkill 杀掉 uninstall 脚本自身
645
+ const selfPid = process.pid;
646
+ execSync(
647
+ `pgrep -f 'myagent|main.py' | grep -v '^${selfPid}$' | xargs -r kill 2>/dev/null; sleep 1; ` +
648
+ `pgrep -f 'myagent|main.py' | grep -v '^${selfPid}$' | xargs -r kill -9 2>/dev/null`,
649
+ { encoding: "utf8", timeout: 10000 }
650
+ );
645
651
  }
646
652
  } catch (_) {}
647
653
 
package/web/api_server.py CHANGED
@@ -4180,21 +4180,34 @@ window.addEventListener('beforeunload', function() {{
4180
4180
  async def handle_list_sessions(self, request):
4181
4181
  if not self.core.memory: return web.json_response([])
4182
4182
  agent = request.query.get("agent", "")
4183
+ conn = self.core.memory._get_conn()
4184
+ _hidden = ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight')
4183
4185
  # 只统计用户可见的消息数(排除 llm_output 和 conversation_insight)
4184
4186
  if agent:
4185
4187
  prefix = f"{agent}_"
4186
- rows = self.core.memory._get_conn().execute(
4187
- "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
4188
- "WHERE category = 'session' AND role != '' "
4189
- "AND key NOT IN ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight') "
4190
- "AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
4191
- (prefix + "%",)).fetchall()
4188
+ # [v1.24.1] 兼容两种会话 ID 格式:
4189
+ # 旧格式: {agent}_web_{timestamp} session_id LIKE 'default_%'
4190
+ # 新格式: sess_{uuid} 通过用户消息 metadata 中的 agent_path 关联
4191
+ metadata_agent_pattern = '%"agent_path":"' + agent + '"%'
4192
+ # 先找出属于该 agent 的所有 session_id(子查询),再统计消息数
4193
+ rows = conn.execute(
4194
+ "SELECT m.session_id, COUNT(*) as cnt, MAX(m.created_at) as last FROM memories m "
4195
+ "WHERE m.category = 'session' AND m.role != '' "
4196
+ "AND m.key NOT IN (?,?,?,?) "
4197
+ "AND m.session_id IN ("
4198
+ " SELECT DISTINCT session_id FROM memories "
4199
+ " WHERE category = 'session' "
4200
+ " AND (session_id LIKE ? OR (session_id LIKE 'sess_%' AND metadata LIKE ?))"
4201
+ ") "
4202
+ "GROUP BY m.session_id ORDER BY last DESC LIMIT 100",
4203
+ (*_hidden, prefix + "%", metadata_agent_pattern)).fetchall()
4192
4204
  else:
4193
- rows = self.core.memory._get_conn().execute(
4205
+ rows = conn.execute(
4194
4206
  "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
4195
4207
  "WHERE category = 'session' AND role != '' "
4196
- "AND key NOT IN ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight') "
4197
- "GROUP BY session_id ORDER BY last DESC LIMIT 100").fetchall()
4208
+ "AND key NOT IN (?,?,?,?) "
4209
+ "GROUP BY session_id ORDER BY last DESC LIMIT 100",
4210
+ (*_hidden,)).fetchall()
4198
4211
  sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
4199
4212
  # 批量获取自定义会话名称
4200
4213
  sids = [s["id"] for s in sessions]
@@ -4225,11 +4238,25 @@ window.addEventListener('beforeunload', function() {{
4225
4238
  if not self.core.memory:
4226
4239
  return web.json_response({"agent": name, "sessions": []})
4227
4240
  prefix = f"{name}_"
4228
- rows = self.core.memory._get_conn().execute(
4229
- "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
4230
- "WHERE category = 'session' AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
4231
- (prefix + "%",)).fetchall()
4232
- sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
4241
+ metadata_agent_pattern = '%"agent_path":"' + name + '"%'
4242
+ conn = self.core.memory._get_conn()
4243
+ # [v1.24.1] 兼容旧格式 (agent_xxx) 和新格式 (sess_xxx)
4244
+ rows = conn.execute(
4245
+ "SELECT DISTINCT session_id FROM memories "
4246
+ "WHERE category = 'session' "
4247
+ "AND (session_id LIKE ? OR (session_id LIKE 'sess_%' AND metadata LIKE ?)) "
4248
+ "LIMIT 100",
4249
+ (prefix + "%", metadata_agent_pattern)).fetchall()
4250
+ matched_sids = [r["session_id"] for r in rows]
4251
+ sessions = []
4252
+ if matched_sids:
4253
+ placeholders = ",".join(["?"] * len(matched_sids))
4254
+ count_rows = conn.execute(
4255
+ f"SELECT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
4256
+ f"WHERE category = 'session' AND session_id IN ({placeholders}) "
4257
+ f"GROUP BY session_id ORDER BY last DESC",
4258
+ matched_sids).fetchall()
4259
+ sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in count_rows]
4233
4260
  # 批量获取自定义会话名称
4234
4261
  sids = [s["id"] for s in sessions]
4235
4262
  name_map = self.core.memory.list_session_names(sids) if sids else {}
@@ -3,7 +3,7 @@
3
3
 
4
4
  (function() {
5
5
  var base = new URL('.', window.location.href).href;
6
- var v = '?v=14';
6
+ var v = '?v=15';
7
7
  var scripts = [
8
8
  'groupchat.js', // 群聊模块(状态 + API + 渲染 + 发送)
9
9
  'flow_engine.js', // 文本处理流引擎(SSE 流式 + 大文本 + 执行事件)
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
6
6
  <title>MyAgent - AI 助手</title>
7
- <link rel="stylesheet" href="chat.css?v=12">
7
+ <link rel="stylesheet" href="chat.css?v=13">
8
8
  </head>
9
9
  <body>
10
10
  <div class="app">
@@ -377,6 +377,6 @@
377
377
  <div id="groupModalContainer"></div>
378
378
 
379
379
  <!-- Load JS scripts (no HTML fragments to fetch) -->
380
- <script src="chat.js?v=10"></script>
380
+ <script src="chat.js?v=11"></script>
381
381
  </body>
382
382
  </html>
@@ -2453,6 +2453,16 @@ async function loadSessions() {
2453
2453
  // 默认选中最新 session
2454
2454
  targetSessionId = state.sessions[0].id;
2455
2455
  }
2456
+ // [v1.24.1] 强制恢复:如果 URL 或 localStorage 有 session ID,但不在 session 列表中
2457
+ // (可能因为 sess_xxx 格式的新会话未匹配到旧格式 LIKE 查询),仍然尝试直接加载
2458
+ if (!targetSessionId) {
2459
+ var fallbackSession = urlSession || state._pendingSessionRestore;
2460
+ if (fallbackSession && fallbackSession !== '__new__') {
2461
+ targetSessionId = fallbackSession;
2462
+ state._pendingSessionRestore = null;
2463
+ console.log('[loadSessions] Session not in list, force restoring:', targetSessionId);
2464
+ }
2465
+ }
2456
2466
 
2457
2467
  if (targetSessionId) {
2458
2468
  await selectSession(targetSessionId);