myagent-ai 1.10.7 → 1.10.8

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.
@@ -453,9 +453,9 @@ class MainAgent(BaseAgent):
453
453
  except Exception as e:
454
454
  logger.warning(f"[{task_id}] 加载历史对话失败: {e}")
455
455
 
456
- # 保存用户消息到短期记忆
456
+ # 保存用户消息到会话记忆
457
457
  if self.memory:
458
- self.memory.add_short_term(
458
+ self.memory.add_session(
459
459
  session_id=context.session_id,
460
460
  role="user",
461
461
  content=context.user_message,
@@ -551,9 +551,9 @@ class MainAgent(BaseAgent):
551
551
  llm_raw = response.content
552
552
  logger.debug(f"[{task_id}] LLM 输出 (前500字): {llm_raw[:500]}")
553
553
 
554
- # 保存 LLM 原始输出到短期记忆(用于回溯和审计)
554
+ # 保存 LLM 原始输出到会话记忆(用于回溯和审计)
555
555
  if self.memory:
556
- self.memory.add_short_term(
556
+ self.memory.add_session(
557
557
  session_id=context.session_id,
558
558
  role="assistant",
559
559
  content=llm_raw,
@@ -588,7 +588,7 @@ class MainAgent(BaseAgent):
588
588
  context.working_memory["final_response"] = final_text
589
589
  await self._emit_v2_event("v2_reasoning", {"content": final_text}, stream_callback)
590
590
  if self.memory:
591
- self.memory.add_short_term(
591
+ self.memory.add_session(
592
592
  session_id=context.session_id,
593
593
  role="assistant",
594
594
  content=final_text,
@@ -601,7 +601,7 @@ class MainAgent(BaseAgent):
601
601
  context.working_memory["final_response"] = final_text
602
602
  await self._emit_v2_event("v2_reasoning", {"content": final_text}, stream_callback)
603
603
  if self.memory:
604
- self.memory.add_short_term(
604
+ self.memory.add_session(
605
605
  session_id=context.session_id,
606
606
  role="assistant",
607
607
  content=final_text,
@@ -741,7 +741,7 @@ class MainAgent(BaseAgent):
741
741
  stream_callback,
742
742
  )
743
743
  if self.memory:
744
- self.memory.add_short_term(
744
+ self.memory.add_session(
745
745
  session_id=context.session_id,
746
746
  role="assistant",
747
747
  content=parsed.ask_user,
@@ -758,7 +758,7 @@ class MainAgent(BaseAgent):
758
758
  context.working_memory["final_response"] = final_text
759
759
  await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
760
760
  if self.memory:
761
- self.memory.add_short_term(
761
+ self.memory.add_session(
762
762
  session_id=context.session_id,
763
763
  role="assistant",
764
764
  content=final_text,
@@ -770,7 +770,7 @@ class MainAgent(BaseAgent):
770
770
  context.working_memory["final_response"] = final_text
771
771
  await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
772
772
  if self.memory:
773
- self.memory.add_short_term(
773
+ self.memory.add_session(
774
774
  session_id=context.session_id,
775
775
  role="assistant",
776
776
  content=final_text,
@@ -1006,16 +1006,16 @@ class MainAgent(BaseAgent):
1006
1006
  content=f"[工具 {tool_name} 执行完成] {'成功' if tool_result.get('success') else '失败'}",
1007
1007
  ))
1008
1008
 
1009
- # 保存工具调用到短期记忆
1009
+ # 保存工具调用到会话记忆
1010
1010
  if self.memory:
1011
- self.memory.add_short_term(
1011
+ self.memory.add_session(
1012
1012
  session_id=context.session_id,
1013
1013
  role="assistant",
1014
1014
  content=f"调用工具: {tool_name}\n参数: {truncate_str(parms, 1000)}",
1015
1015
  key="tool_call",
1016
1016
  importance=0.4,
1017
1017
  )
1018
- self.memory.add_short_term(
1018
+ self.memory.add_session(
1019
1019
  session_id=context.session_id,
1020
1020
  role="tool",
1021
1021
  content=f"[{tool_name}] {'成功' if tool_result.get('success') else '失败'}\n{truncate_str(output_str, 5000)}",
@@ -1048,7 +1048,7 @@ class MainAgent(BaseAgent):
1048
1048
  context.working_memory["final_response"] = final_text
1049
1049
  await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
1050
1050
  if self.memory:
1051
- self.memory.add_short_term(
1051
+ self.memory.add_session(
1052
1052
  session_id=context.session_id,
1053
1053
  role="assistant",
1054
1054
  content=final_text,
@@ -1075,7 +1075,7 @@ class MainAgent(BaseAgent):
1075
1075
  context.working_memory["final_response"] = final_text
1076
1076
  await self._emit_v2_event("v2_reasoning", {"content": truncate_str(final_text, 3000)}, stream_callback)
1077
1077
  if self.memory:
1078
- self.memory.add_short_term(
1078
+ self.memory.add_session(
1079
1079
  session_id=context.session_id,
1080
1080
  role="assistant",
1081
1081
  content=final_text,
@@ -1084,14 +1084,14 @@ class MainAgent(BaseAgent):
1084
1084
 
1085
1085
  logger.info(f"[{task_id}] finish=false 且 need_callback=true,回调 LLM...")
1086
1086
 
1087
- # 回调前,保存当前轮次的 LLM 输出到短期记忆
1087
+ # 回调前,保存当前轮次的 LLM 输出到会话记忆
1088
1088
  # 这样每轮工具调用都有对应的 assistant 消息记录
1089
1089
  if self.memory:
1090
1090
  _round_items = _v2_reasoning_collected[_reasoning_len_before_round:]
1091
1091
  if _round_items:
1092
1092
  _round_output = "\n".join(_round_items)
1093
1093
  if _round_output.strip():
1094
- self.memory.add_short_term(
1094
+ self.memory.add_session(
1095
1095
  session_id=context.session_id,
1096
1096
  role="assistant",
1097
1097
  content=_round_output,
@@ -1102,7 +1102,7 @@ class MainAgent(BaseAgent):
1102
1102
  if self.memory and _v2_reasoning_collected:
1103
1103
  _fallback_text = "\n".join(_v2_reasoning_collected)
1104
1104
  if _fallback_text.strip():
1105
- self.memory.add_short_term(
1105
+ self.memory.add_session(
1106
1106
  session_id=context.session_id,
1107
1107
  role="assistant",
1108
1108
  content=_fallback_text,
@@ -116,7 +116,7 @@ class MemoryAgent(BaseAgent):
116
116
  )
117
117
 
118
118
  # 修剪旧消息
119
- max_msgs = self.config.memory.max_short_term
119
+ max_msgs = self.config.memory.max_session
120
120
  self.memory.prune_conversation(session_id, max_msgs)
121
121
 
122
122
  logger.debug(f"对话已保存到会话记忆 (session={session_id})")
@@ -162,7 +162,7 @@ class MemoryAgent(BaseAgent):
162
162
  if not self.memory:
163
163
  return
164
164
 
165
- entries = self.memory.get_working(session_id)
165
+ entries = self.memory._query(session_id=session_id, category="session", limit=100)
166
166
  context.working_memory["task_progress"] = [
167
167
  {"key": e.key, "content": e.content, "metadata": e.metadata}
168
168
  for e in entries
package/config.py CHANGED
@@ -50,11 +50,6 @@ class MemoryConfig:
50
50
  auto_summarize: bool = True # 自动总结开关
51
51
  summarize_threshold: int = 20 # 触发总结的对话轮数
52
52
 
53
- # 兼容旧配置名
54
- @property
55
- def max_short_term(self) -> int:
56
- return self.max_session
57
-
58
53
 
59
54
  @dataclass
60
55
  class ExecutorConfig:
package/memory/manager.py CHANGED
@@ -6,10 +6,6 @@ memory/manager.py - 记忆管理器
6
6
  - 会话记忆 (session): 当前会话的对话上下文和任务进度,仅本 session 可检索
7
7
 
8
8
  所有记忆通过 session_id 隔离,全局记忆可跨会话检索。
9
-
10
- 向后兼容:
11
- 旧 API (add_short_term, add_working, add_long_term) 仍然可用,
12
- 内部自动映射到新的 session / global 分类。
13
9
  """
14
10
  from __future__ import annotations
15
11
 
@@ -95,23 +91,13 @@ class MemoryManager:
95
91
  - session (会话记忆): 对话上下文 + 任务进度,按 session_id 隔离
96
92
  - global (全局记忆): 跨会话持久知识,所有 session 可检索
97
93
 
98
- 向后兼容:
99
- 旧方法 add_short_term / add_working / add_long_term 仍可正常使用,
100
- 内部自动映射到 session / global 分类。
101
- 旧分类值 short_term、working、long_term 在查询时自动包含。
102
-
103
94
  使用示例:
104
95
  mm = MemoryManager(db_path="~/.myagent/data/memory.db")
105
96
  mm.initialize()
106
97
 
107
- # 新 API
108
98
  mm.add_session("s1", role="user", content="帮我创建一个Python项目")
109
99
  mm.add_global(content="偏好使用Python, TypeScript")
110
100
 
111
- # 旧 API (仍然可用)
112
- mm.add_short_term("s1", "user", "帮我创建一个Python项目")
113
- mm.add_long_term("user_prefs", "coding_style", "偏好使用Python, TypeScript")
114
-
115
101
  # 查询对话历史
116
102
  history = mm.get_conversation("s1")
117
103
 
@@ -183,29 +169,6 @@ class MemoryManager:
183
169
  self._local.conn.close()
184
170
  self._local.conn = None
185
171
 
186
- # ==========================================================================
187
- # 分类映射 (向后兼容)
188
- # ==========================================================================
189
-
190
- def _normalize_category(self, category: str) -> str:
191
- """Map old category values to new ones:
192
- short_term, working → session
193
- long_term → global
194
- """
195
- _MAP = {"short_term": "session", "working": "session", "long_term": "global"}
196
- return _MAP.get(category, category)
197
-
198
- def _expand_category(self, category: str) -> list:
199
- """Expand category for SQL IN clause (backward compat):
200
- "session" → ["session", "short_term", "working"]
201
- "global" → ["global", "long_term"]
202
- """
203
- if category == "session":
204
- return ["session", "short_term", "working"]
205
- elif category == "global":
206
- return ["global", "long_term"]
207
- return [category]
208
-
209
172
  # ==========================================================================
210
173
  # 基础 CRUD
211
174
  # ==========================================================================
@@ -252,10 +215,8 @@ class MemoryManager:
252
215
  conditions.append("session_id = ?")
253
216
  params.append(session_id)
254
217
  if category:
255
- expanded = self._expand_category(category)
256
- placeholders = ",".join("?" for _ in expanded)
257
- conditions.append(f"category IN ({placeholders})")
258
- params.extend(expanded)
218
+ conditions.append("category = ?")
219
+ params.append(category)
259
220
  if key:
260
221
  conditions.append("key = ?")
261
222
  params.append(key)
@@ -323,58 +284,13 @@ class MemoryManager:
323
284
  )
324
285
  return self._insert(entry)
325
286
 
326
- # --- 兼容别名 ---
327
- def add_short_term(self, session_id, role, content, key="", importance=0.5) -> str:
328
- """[兼容] → add_session()"""
329
- return self.add_session(session_id=session_id, role=role, content=content, key=key, importance=importance)
330
-
331
- def add_working(self, session_id, key, content, metadata=None) -> str:
332
- """[兼容] → add_session()"""
333
- return self.add_session(session_id=session_id, key=key, content=content, importance=0.7, metadata=metadata or {})
334
-
335
- def get_working(self, session_id, key="") -> List[MemoryEntry]:
336
- """[兼容] 获取会话记忆中 key 非空的条目"""
337
- conn = self._get_conn()
338
- cats = self._expand_category("session")
339
- placeholders = ",".join("?" for _ in cats)
340
- conditions = [f"session_id = ?", f"category IN ({placeholders})", "key != ''"]
341
- params = [session_id] + cats
342
- if key:
343
- conditions.append("key = ?")
344
- params.append(key)
345
- where = " AND ".join(conditions)
346
- sql = f"SELECT * FROM memories WHERE {where} ORDER BY created_at DESC LIMIT 100"
347
- rows = conn.execute(sql, params).fetchall()
348
- return [MemoryEntry.from_row(row) for row in rows]
349
-
350
- def update_working(self, memory_id, content, **updates):
351
- """[兼容] → _update_content()"""
352
- self._update_content(memory_id, content, **updates)
353
-
354
- def clear_working(self, session_id) -> int:
355
- """[兼容] 清空会话记忆中 key 非空的条目"""
356
- conn = self._get_conn()
357
- cats = self._expand_category("session")
358
- placeholders = ",".join("?" for _ in cats)
359
- params = [session_id] + cats
360
- cursor = conn.execute(
361
- f"DELETE FROM memories WHERE session_id = ? AND category IN ({placeholders}) AND key != ''",
362
- params,
363
- )
364
- conn.commit()
365
- return cursor.rowcount
366
-
367
287
  def get_conversation(self, session_id, limit=500, include_roles=None) -> List[MemoryEntry]:
368
- """获取对话历史(搜索 session 分类中 role 非空的条目,兼容旧 short_term 数据)"""
288
+ """获取对话历史(session 分类中 role 非空的条目)"""
369
289
  conn = self._get_conn()
370
- cats = self._expand_category("session")
371
- placeholders = ",".join("?" for _ in cats)
372
- conditions = ["session_id = ?", f"category IN ({placeholders})", "role != ''"]
373
- params = [session_id] + cats
374
- where = " AND ".join(conditions)
375
- sql = f"SELECT * FROM memories WHERE {where} ORDER BY created_at ASC LIMIT ?"
376
- params.append(limit)
377
- rows = conn.execute(sql, params).fetchall()
290
+ sql = """SELECT * FROM memories
291
+ WHERE session_id = ? AND category = 'session' AND role != ''
292
+ ORDER BY created_at ASC LIMIT ?"""
293
+ rows = conn.execute(sql, (session_id, limit)).fetchall()
378
294
  entries = [MemoryEntry.from_row(row) for row in rows]
379
295
  if include_roles:
380
296
  entries = [e for e in entries if e.role in include_roles]
@@ -403,14 +319,7 @@ class MemoryManager:
403
319
 
404
320
  def clear_conversation(self, session_id) -> int:
405
321
  """清空会话对话历史"""
406
- count = self._delete(session_id, category="session")
407
- # 兼容旧数据
408
- for old_cat in ("short_term", "working"):
409
- try:
410
- count += self._delete(session_id, category=old_cat)
411
- except Exception:
412
- pass
413
- return count
322
+ return self._delete(session_id, category="session")
414
323
 
415
324
  def delete_session(self, session_id: str) -> int:
416
325
  """删除会话的所有记忆(对话、工作记忆、长期记忆等),彻底删除该会话"""
@@ -504,11 +413,6 @@ class MemoryManager:
504
413
  )
505
414
  return self._insert(entry)
506
415
 
507
- # --- 兼容别名 ---
508
- def add_long_term(self, session_id="global", key="", content="", summary="", importance=0.7, metadata=None) -> str:
509
- """[兼容] → add_global()"""
510
- return self.add_global(session_id=session_id, key=key, content=content, summary=summary, importance=importance, metadata=metadata)
511
-
512
416
  def find_duplicate_memory(
513
417
  self,
514
418
  content: str,
@@ -535,10 +439,8 @@ class MemoryManager:
535
439
  return None # 空内容不查重
536
440
 
537
441
  conn = self._get_conn()
538
- cats = self._expand_category("global")
539
- placeholders = ",".join("?" for _ in cats)
540
- conditions = [f"category IN ({placeholders})"]
541
- params: list = list(cats)
442
+ conditions = ["category = 'global'"]
443
+ params: list = []
542
444
 
543
445
  if session_id:
544
446
  conditions.append("session_id = ?")
@@ -633,13 +535,11 @@ class MemoryManager:
633
535
  return True
634
536
  return False
635
537
 
636
- def get_long_term(self, session_id="global", key="", limit=50) -> List[MemoryEntry]:
538
+ def get_global_memories(self, session_id="global", key="", limit=50) -> List[MemoryEntry]:
637
539
  """获取全局记忆"""
638
540
  conn = self._get_conn()
639
- cats = self._expand_category("global")
640
- placeholders = ",".join("?" for _ in cats)
641
- conditions = ["category IN (%s)" % placeholders]
642
- params = list(cats)
541
+ conditions = ["category = 'global'"]
542
+ params: list = []
643
543
  if session_id:
644
544
  conditions.insert(0, "session_id = ?")
645
545
  params.insert(0, session_id)
@@ -654,15 +554,15 @@ class MemoryManager:
654
554
 
655
555
  def get_preferences(self, session_id: str = "global") -> List[MemoryEntry]:
656
556
  """获取用户偏好"""
657
- return self.get_long_term(session_id, key="user_pref")
557
+ return self.get_global_memories(session_id, key="user_pref")
658
558
 
659
559
  def get_experience(self, session_id: str = "global") -> List[MemoryEntry]:
660
560
  """获取技能经验"""
661
- return self.get_long_term(session_id, key="skill_experience")
561
+ return self.get_global_memories(session_id, key="skill_experience")
662
562
 
663
563
  def get_task_summaries(self, session_id: str = "global") -> List[MemoryEntry]:
664
564
  """获取历史任务总结"""
665
- return self.get_long_term(session_id, key="task_summary")
565
+ return self.get_global_memories(session_id, key="task_summary")
666
566
 
667
567
  # ==========================================================================
668
568
  # 记忆搜索
@@ -812,10 +712,8 @@ class MemoryManager:
812
712
  conditions.append("session_id = ?")
813
713
  params.append(session_id)
814
714
  if category:
815
- expanded = self._expand_category(category)
816
- placeholders = ",".join("?" for _ in expanded)
817
- conditions.append(f"category IN ({placeholders})")
818
- params.extend(expanded)
715
+ conditions.append("category = ?")
716
+ params.append(category)
819
717
 
820
718
  # 过滤过期
821
719
  conditions.append("(expires_at = '' OR expires_at > ?)")
@@ -959,7 +857,7 @@ class MemoryManager:
959
857
  original_count: int = 0,
960
858
  ) -> str:
961
859
  """保存对话总结为全局记忆"""
962
- return self.add_long_term(
860
+ return self.add_global(
963
861
  session_id=session_id,
964
862
  key="conversation_summary",
965
863
  content=summary,
@@ -985,7 +883,7 @@ class MemoryManager:
985
883
  session_id: str = "global",
986
884
  ):
987
885
  """记录错误模式及修复方案"""
988
- self.add_long_term(
886
+ self.add_global(
989
887
  session_id=session_id,
990
888
  key="error_pattern",
991
889
  content=f"错误: {error}\n修复: {fix}",
@@ -1002,22 +900,17 @@ class MemoryManager:
1002
900
  conn = self._get_conn()
1003
901
  stats = {}
1004
902
  for cat in ("session", "global"):
1005
- cats = self._expand_category(cat)
1006
- placeholders = ",".join("?" for _ in cats)
1007
903
  row = conn.execute(
1008
- f"SELECT COUNT(*) as cnt FROM memories WHERE category IN ({placeholders})",
1009
- cats,
904
+ "SELECT COUNT(*) as cnt FROM memories WHERE category = ?",
905
+ (cat,),
1010
906
  ).fetchone()
1011
907
  stats[f"{cat}_count"] = row["cnt"]
1012
-
1013
908
  total = conn.execute("SELECT COUNT(*) as cnt FROM memories").fetchone()
1014
909
  stats["total_count"] = total["cnt"]
1015
-
1016
910
  sessions = conn.execute(
1017
911
  "SELECT COUNT(DISTINCT session_id) as cnt FROM memories"
1018
912
  ).fetchone()
1019
913
  stats["distinct_sessions"] = sessions["cnt"]
1020
-
1021
914
  return stats
1022
915
 
1023
916
  def cleanup_expired(self) -> int:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.10.7",
3
+ "version": "1.10.8",
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
@@ -278,8 +278,8 @@ class ApiServer:
278
278
  r.add_get("/api/session/status", self.handle_session_status_query) # query param version
279
279
  r.add_get("/api/memory/stats", self.handle_memory_stats)
280
280
  r.add_get("/api/memory/search", self.handle_memory_search)
281
- r.add_get("/api/memory/long-term", self.handle_list_long_term)
282
- r.add_delete("/api/memory/long-term/{mid}", self.handle_delete_long_term)
281
+ r.add_get("/api/memory/list", self.handle_memory_list)
282
+ r.add_delete("/api/memory/{mid}", self.handle_delete_memory)
283
283
  r.add_post("/api/memory/cleanup", self.handle_memory_cleanup)
284
284
  # 权限管理
285
285
  r.add_get("/api/permissions", self.handle_get_permissions)
@@ -551,7 +551,7 @@ class ApiServer:
551
551
  response = await self.core.process_message(clean_message, session_id)
552
552
 
553
553
  # 记忆保存已由 MainAgent._process_inner() 完成,此处不再重复保存
554
- # (MainAgent 内部会保存 user + assistant 消息到短期记忆)
554
+ # (MainAgent 内部会保存 user + assistant 消息到会话记忆)
555
555
 
556
556
  # ── 收集执行事件(供前端展示命令执行过程) ──
557
557
  exec_events = []
@@ -795,11 +795,11 @@ class ApiServer:
795
795
  # 使用已累积的结果(如果有)
796
796
  saved = result_store.get("full_response", "")
797
797
  if saved:
798
- self.core.memory.add_short_term(
798
+ self.core.memory.add_session(
799
799
  session_id=session_id, role="assistant", content=saved,
800
800
  )
801
801
  else:
802
- self.core.memory.add_short_term(
802
+ self.core.memory.add_session(
803
803
  session_id=session_id, role="assistant",
804
804
  content=f"⚠️ [执行异常] {str(e)[:200]}",
805
805
  )
@@ -1647,7 +1647,7 @@ class ApiServer:
1647
1647
  if self.core.memory:
1648
1648
  rows = self.core.memory._get_conn().execute(
1649
1649
  "SELECT session_id, COUNT(*) as cnt FROM memories "
1650
- "WHERE category IN ('session', 'short_term', 'working') GROUP BY session_id").fetchall()
1650
+ "WHERE category = 'session' GROUP BY session_id").fetchall()
1651
1651
  session_counts = {}
1652
1652
  for r in rows:
1653
1653
  sid = r["session_id"]
@@ -1667,7 +1667,7 @@ class ApiServer:
1667
1667
  if self.core.memory:
1668
1668
  rows = self.core.memory._get_conn().execute(
1669
1669
  "SELECT session_id, COUNT(*) as cnt FROM memories "
1670
- "WHERE category IN ('session', 'short_term', 'working') GROUP BY session_id").fetchall()
1670
+ "WHERE category = 'session' GROUP BY session_id").fetchall()
1671
1671
  session_counts = {}
1672
1672
  for r in rows:
1673
1673
  sid = r["session_id"]
@@ -2301,12 +2301,12 @@ class ApiServer:
2301
2301
  prefix = f"{agent}_"
2302
2302
  rows = self.core.memory._get_conn().execute(
2303
2303
  "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
2304
- "WHERE category IN ('session', 'short_term', 'working') AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
2304
+ "WHERE category = 'session' AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
2305
2305
  (prefix + "%",)).fetchall()
2306
2306
  else:
2307
2307
  rows = self.core.memory._get_conn().execute(
2308
2308
  "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
2309
- "WHERE category IN ('session', 'short_term', 'working') GROUP BY session_id ORDER BY last DESC LIMIT 100").fetchall()
2309
+ "WHERE category = 'session' GROUP BY session_id ORDER BY last DESC LIMIT 100").fetchall()
2310
2310
  sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
2311
2311
  # 批量获取自定义会话名称
2312
2312
  sids = [s["id"] for s in sessions]
@@ -2319,9 +2319,9 @@ class ApiServer:
2319
2319
  preview_rows = conn.execute(
2320
2320
  f"SELECT m1.session_id, m1.content FROM memories m1 "
2321
2321
  f"INNER JOIN (SELECT session_id, MAX(created_at) as max_t FROM memories "
2322
- f"WHERE session_id IN ({placeholders}) AND role='user' AND category IN ('session', 'short_term', 'working') "
2322
+ f"WHERE session_id IN ({placeholders}) AND role='user' AND category = 'session' "
2323
2323
  f"GROUP BY session_id) m2 ON m1.session_id = m2.session_id AND m1.created_at = m2.max_t "
2324
- f"WHERE m1.role='user' AND m1.category IN ('session', 'short_term', 'working')",
2324
+ f"WHERE m1.role='user' AND m1.category = 'session'",
2325
2325
  sids
2326
2326
  ).fetchall()
2327
2327
  for pr in preview_rows:
@@ -2339,7 +2339,7 @@ class ApiServer:
2339
2339
  prefix = f"{name}_"
2340
2340
  rows = self.core.memory._get_conn().execute(
2341
2341
  "SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
2342
- "WHERE category IN ('session', 'short_term', 'working') AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
2342
+ "WHERE category = 'session' AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
2343
2343
  (prefix + "%",)).fetchall()
2344
2344
  sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
2345
2345
  # 批量获取自定义会话名称
@@ -2473,11 +2473,12 @@ class ApiServer:
2473
2473
  "role": e.role, "session_id": e.session_id, "created_at": e.created_at,
2474
2474
  } for e in results])
2475
2475
 
2476
- async def handle_list_long_term(self, request):
2476
+ async def handle_memory_list(self, request):
2477
2477
  if not self.core.memory: return web.json_response([])
2478
2478
  cat = request.query.get("category", "global")
2479
2479
  limit = int(request.query.get("limit", "50"))
2480
- entries = self.core.memory._query(category=cat, limit=limit, order_by="created_at DESC")
2480
+ session_id = request.query.get("session_id", "")
2481
+ entries = self.core.memory._query(category=cat, session_id=session_id, limit=limit, order_by="created_at DESC")
2481
2482
  return web.json_response([{
2482
2483
  "id": e.id, "key": e.key, "content": e.content[:500],
2483
2484
  "summary": e.summary, "importance": e.importance,
@@ -2485,7 +2486,7 @@ class ApiServer:
2485
2486
  "session_id": e.session_id, "created_at": e.created_at,
2486
2487
  } for e in entries])
2487
2488
 
2488
- async def handle_delete_long_term(self, request):
2489
+ async def handle_delete_memory(self, request):
2489
2490
  if self.core.memory:
2490
2491
  self.core.memory._get_conn().execute("DELETE FROM memories WHERE id=?", (request.match_info["mid"],))
2491
2492
  self.core.memory._get_conn().commit()
@@ -3256,7 +3257,7 @@ class ApiServer:
3256
3257
  """使用流式LLM调用处理消息,支持完整的agent循环(工具调用/操作执行)+ 实时流式输出
3257
3258
 
3258
3259
  核心改进:
3259
- - 每轮迭代结束后增量保存已流式输出的文本到短期记忆(即使客户端断开也不丢失)
3260
+ - 每轮迭代结束后增量保存已流式输出的文本到会话记忆(即使客户端断开也不丢失)
3260
3261
  - 使用 frequency_penalty 减少大模型重复输出
3261
3262
  - 最终保存时使用累积文本而非 final_response,确保完整内容不丢失
3262
3263
 
@@ -3390,11 +3391,11 @@ class ApiServer:
3390
3391
  recent = agent.memory.get_conversation(session_id, limit=3)
3391
3392
  _has_assistant = any(e.role == "assistant" for e in recent)
3392
3393
  if not _has_assistant and final_response and final_response.strip():
3393
- agent.memory.add_short_term(
3394
+ agent.memory.add_session(
3394
3395
  session_id=session_id, role="assistant", content=final_response,
3395
3396
  )
3396
3397
 
3397
- # ── 保存工具调用过程到短期记忆(V2 路由) ──
3398
+ # ── 保存工具调用过程到会话记忆(V2 路由) ──
3398
3399
  if agent.memory and agent._execution_events:
3399
3400
  try:
3400
3401
  from core.utils import truncate_str
@@ -3424,7 +3425,7 @@ class ApiServer:
3424
3425
  pass # code_result is duplicate of code_exec with final status
3425
3426
  if tool_summary_parts:
3426
3427
  exec_log = "\n".join(tool_summary_parts)
3427
- agent.memory.add_short_term(
3428
+ agent.memory.add_session(
3428
3429
  session_id=session_id,
3429
3430
  role="tool",
3430
3431
  content=exec_log,
@@ -3782,7 +3783,7 @@ class ApiServer:
3782
3783
  if accumulated_text and len(accumulated_text) > _saved_text_length:
3783
3784
  new_save_text = accumulated_text[_saved_text_length:]
3784
3785
  if new_save_text.strip():
3785
- agent.memory.add_short_term(
3786
+ agent.memory.add_session(
3786
3787
  session_id=session_id, role="assistant", content=new_save_text,
3787
3788
  )
3788
3789
  _saved_text_length = len(accumulated_text)
@@ -3932,7 +3933,7 @@ class ApiServer:
3932
3933
  if accumulated_text and len(accumulated_text) > _saved_text_length:
3933
3934
  new_save_text = accumulated_text[_saved_text_length:]
3934
3935
  if new_save_text.strip():
3935
- agent.memory.add_short_term(
3936
+ agent.memory.add_session(
3936
3937
  session_id=session_id, role="assistant", content=new_save_text,
3937
3938
  )
3938
3939
  _saved_text_length = len(accumulated_text)
@@ -3956,7 +3957,7 @@ class ApiServer:
3956
3957
  if agent.memory and content and len(content) > _saved_text_length:
3957
3958
  new_save_text = content[_saved_text_length:]
3958
3959
  if new_save_text.strip():
3959
- agent.memory.add_short_term(
3960
+ agent.memory.add_session(
3960
3961
  session_id=session_id, role="assistant", content=new_save_text,
3961
3962
  )
3962
3963
  _saved_text_length = len(content)
@@ -3976,14 +3977,14 @@ class ApiServer:
3976
3977
  if agent.memory and saved_response and len(saved_response) > _saved_text_length:
3977
3978
  new_text = saved_response[_saved_text_length:]
3978
3979
  if new_text.strip():
3979
- agent.memory.add_short_term(
3980
+ agent.memory.add_session(
3980
3981
  session_id=session_id, role="assistant", content=new_text,
3981
3982
  )
3982
3983
  _saved_text_length = len(saved_response)
3983
3984
  elif agent.memory and not saved_response:
3984
- agent.memory.add_short_term(session_id=session_id, role="assistant", content="(执行完成,无文本回复)")
3985
+ agent.memory.add_session(session_id=session_id, role="assistant", content="(执行完成,无文本回复)")
3985
3986
 
3986
- # ── 保存工具调用过程到短期记忆(供历史记录查看) ──
3987
+ # ── 保存工具调用过程到会话记忆(供历史记录查看) ──
3987
3988
  if agent.memory and agent._execution_events:
3988
3989
  try:
3989
3990
  from core.utils import truncate_str
@@ -4013,7 +4014,7 @@ class ApiServer:
4013
4014
  pass # code_result is duplicate of code_exec with final status
4014
4015
  if tool_summary_parts:
4015
4016
  exec_log = "\n".join(tool_summary_parts)
4016
- agent.memory.add_short_term(
4017
+ agent.memory.add_session(
4017
4018
  session_id=session_id,
4018
4019
  role="tool",
4019
4020
  content=exec_log,
@@ -2047,7 +2047,7 @@ function _renderMessagesInner() {
2047
2047
  <div class="capability"><span class="cap-icon">💻</span> 代码编写与执行</div>
2048
2048
  <div class="capability"><span class="cap-icon">🔍</span> 网络搜索与阅读</div>
2049
2049
  <div class="capability"><span class="cap-icon">📁</span> 文件管理与操作</div>
2050
- <div class="capability"><span class="cap-icon">🧠</span> 长期记忆系统</div>
2050
+ <div class="capability"><span class="cap-icon">🧠</span> 全局记忆系统</div>
2051
2051
  <div class="capability"><span class="cap-icon">🌐</span> 多平台接入</div>
2052
2052
  <div class="capability"><span class="cap-icon">🛠️</span> 系统命令执行</div>
2053
2053
  </div>
@@ -44,7 +44,7 @@
44
44
  <div class="capability"><span class="cap-icon">💻</span> 代码编写与执行</div>
45
45
  <div class="capability"><span class="cap-icon">🔍</span> 网络搜索与阅读</div>
46
46
  <div class="capability"><span class="cap-icon">📁</span> 文件管理与操作</div>
47
- <div class="capability"><span class="cap-icon">🧠</span> 长期记忆系统</div>
47
+ <div class="capability"><span class="cap-icon">🧠</span> 全局记忆系统</div>
48
48
  <div class="capability"><span class="cap-icon">🌐</span> 多平台接入</div>
49
49
  <div class="capability"><span class="cap-icon">🛠️</span> 系统命令执行</div>
50
50
  </div>
package/web/ui/index.html CHANGED
@@ -346,9 +346,8 @@ async function renderDashboard(){
346
346
  <div class="stat"><div class="label">已注册技能</div><div class="value">${s.skills||0}</div></div>
347
347
  <div class="stat"><div class="label">会话数</div><div class="value">${m.session_count||0}</div></div>
348
348
  <div class="stat"><div class="label">任务队列</div><div class="value">${s.queue?.total_submitted||0} 提交</div></div>
349
- <div class="stat"><div class="label">短期记忆</div><div class="value">${m.short_term_count||0}</div></div>
350
- <div class="stat"><div class="label">工作记忆</div><div class="value">${m.working_count||0}</div></div>
351
- <div class="stat"><div class="label">长期记忆</div><div class="value">${m.long_term_count||0}</div></div>
349
+ <div class="stat"><div class="label">会话记忆</div><div class="value">${m.session_count||0}</div></div>
350
+ <div class="stat"><div class="label">全局记忆</div><div class="value">${m.global_count||0}</div></div>
352
351
  </div>`;
353
352
  }
354
353
 
@@ -913,13 +912,13 @@ function enterSession(sid,agentName){
913
912
  }
914
913
 
915
914
  // ========== Memory ==========
916
- let _memCategory='long_term';
915
+ let _memCategory='global';
917
916
  async function renderMemory(){
918
917
  let stats={},lt=[];
919
918
  try{stats=await api('/api/memory/stats')}catch(e){stats={error:e.message}}
920
- try{lt=await api('/api/memory/long-term?category='+encodeURIComponent(_memCategory))}catch(e){lt=[]}
919
+ try{lt=await api('/api/memory/list?category='+encodeURIComponent(_memCategory))}catch(e){lt=[]}
921
920
  if(stats.error){$('content').innerHTML='<div class="empty" style="color:var(--danger)">记忆系统异常: '+escHtml(stats.error)+'</div>';return}
922
- const cats=[{k:'short_term',l:'短期记忆'},{k:'working',l:'工作记忆'},{k:'long_term',l:'长期记忆'}];
921
+ const cats=[{k:'global',l:'全局记忆'},{k:'session',l:'会话记忆'}];
923
922
  let tabHtml='<div class="flex gap-8 mb-8">';
924
923
  for(const c of cats){
925
924
  const active=c.k===_memCategory?'btn-primary':'btn-ghost';
@@ -927,22 +926,19 @@ async function renderMemory(){
927
926
  tabHtml+=`<button class="btn ${active}" onclick="_memCategory='${c.k}';renderMemory()">${c.l} (${count})</button>`;
928
927
  }
929
928
  tabHtml+='</div>';
930
- let html=`<div class="grid" style="grid-template-columns:repeat(4,1fr);margin-bottom:16px">
929
+ let html=`<div class="grid" style="grid-template-columns:repeat(3,1fr);margin-bottom:16px">
931
930
  <div class="stat"><div class="label">总计</div><div class="value">${stats.total_count||0}</div></div>
932
- <div class="stat"><div class="label">短期</div><div class="value">${stats.short_term_count||0}</div></div>
933
- <div class="stat"><div class="label">工作</div><div class="value">${stats.working_count||0}</div></div>
934
- <div class="stat"><div class="label">长期</div><div class="value">${stats.long_term_count||0}</div></div></div>`;
931
+ <div class="stat"><div class="label">全局记忆</div><div class="value">${stats.global_count||0}</div></div>
932
+ <div class="stat"><div class="label">会话记忆</div><div class="value">${stats.session_count||0}</div></div></div>`;
935
933
  html+=tabHtml;
936
934
  html+='<div class="flex gap-8 mb-16"><input id="memSearch" placeholder="搜索记忆..." onkeydown="if(event.key===\'Enter\')searchMemory()" style="max-width:400px"><button class="btn btn-primary" onclick="searchMemory()">搜索</button><button class="btn btn-ghost" onclick="cleanupMemory()">清理过期</button></div>';
937
935
  if(lt&&lt.length){
938
- const isShortTerm=_memCategory==='short_term';
939
- const showSession=isShortTerm;
940
- const showRole=isShortTerm;
936
+ const isSession=_memCategory==='session';
941
937
  let thHtml='<tr>';
942
938
  thHtml+='<th>Key</th><th>内容</th>';
943
- if(showRole)thHtml+='<th>角色</th>';
944
- if(showSession)thHtml+='<th>会话</th>';
945
- if(!isShortTerm)thHtml+='<th>重要性</th>';
939
+ thHtml+='<th>角色</th>';
940
+ thHtml+='<th>会话</th>';
941
+ if(!isSession)thHtml+='<th>重要性</th>';
946
942
  thHtml+='<th></th></tr>';
947
943
  html+='<table>'+thHtml;
948
944
  for(const e of lt){
@@ -952,14 +948,14 @@ async function renderMemory(){
952
948
  if(content.length>300)contentPreview+=`<span style="color:var(--text3)">... (${content.length}字)</span>`;
953
949
  html+='<tr><td style="white-space:nowrap;max-width:120px;overflow:hidden;text-overflow:ellipsis">'+escHtml(e.key||e.role||'-')+'</td>';
954
950
  html+='<td style="max-width:600px;word-break:break-word;font-size:13px">'+contentPreview+'</td>';
955
- if(showRole)html+='<td style="white-space:nowrap">'+escHtml(e.role||'')+'</td>';
956
- if(showSession)html+='<td style="white-space:nowrap;max-width:140px;overflow:hidden;text-overflow:ellipsis;font-size:12px;color:var(--text3)" title="'+escHtml(e.session_id||'')+'">'+escHtml((e.session_id||'').split('_web_')[0])+'</td>';
957
- if(!isShortTerm)html+='<td>'+(e.importance!=null?e.importance.toFixed(2):'')+'</td>';
951
+ html+='<td style="white-space:nowrap">'+escHtml(e.role||'')+'</td>';
952
+ html+='<td style="white-space:nowrap;max-width:140px;overflow:hidden;text-overflow:ellipsis;font-size:12px;color:var(--text3)" title="'+escHtml(e.session_id||'')+'">'+escHtml((e.session_id||'').split('_web_')[0])+'</td>';
953
+ if(!isSession)html+='<td>'+(e.importance!=null?e.importance.toFixed(2):'')+'</td>';
958
954
  html+='<td><button class="btn btn-sm btn-danger" onclick="deleteMemory(\''+e.id+'\')">删除</button></td></tr>';
959
955
  }
960
956
  html+='</table>';
961
957
  }else{
962
- html+='<div class="empty">暂无'+(_memCategory==='short_term'?'短期':_memCategory==='working'?'工作':'长期')+'记忆</div>';
958
+ html+='<div class="empty">暂无'+(_memCategory==='session'?'会话':'全局')+'记忆</div>';
963
959
  }
964
960
  $('content').innerHTML=html;
965
961
  }
@@ -979,7 +975,7 @@ async function searchMemory(){
979
975
  }
980
976
  html+='<button class="btn btn-ghost mt-8" onclick="renderMemory()">返回</button>';$('content').innerHTML=html;
981
977
  }
982
- async function deleteMemory(id){await api(`/api/memory/long-term/${id}`,{method:'DELETE'});renderMemory()}
978
+ async function deleteMemory(id){await api(`/api/memory/${id}`,{method:'DELETE'});renderMemory()}
983
979
  async function cleanupMemory(){const r=await api('/api/memory/cleanup',{method:'POST'});showToast('清理了 '+(r.cleaned||0)+' 条','success');renderMemory()}
984
980
 
985
981
  // ========== 权限管理 ==========
@@ -1985,7 +1981,7 @@ async function sysLoadPreview(){
1985
1981
  lines.push('<span class="key">执行引擎:</span> '+escHtml(c.executor.execution_mode||'local')+' | Timeout: '+(c.executor.timeout||300)+'s');
1986
1982
  }
1987
1983
  if(c.memory){
1988
- lines.push('<span class="key">记忆:</span> 短期 '+(c.memory.max_short_term||50)+' 轮 | 自动总结: '+(c.memory.auto_summarize?'开':'关'));
1984
+ lines.push('<span class="key">记忆:</span> 会话 '+(c.memory.max_session||50)+' 轮 | 自动总结: '+(c.memory.auto_summarize?'开':'关'));
1989
1985
  }
1990
1986
  if(c.agent){
1991
1987
  lines.push('<span class="key">Agent:</span> 最大迭代 '+(c.agent.max_iterations||30)+' | 并行 '+(c.agent.max_parallel||3));