myagent-ai 1.10.7 → 1.10.9

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,
@@ -1137,6 +1137,10 @@ class MainAgent(BaseAgent):
1137
1137
  code_lang = params.get("language", "python")
1138
1138
  code_text = params.get("code", parms_str)
1139
1139
  if self.executor:
1140
+ # 注入权限检查器(V1 路径在 api_server 中设置,V2 路径需要在此设置)
1141
+ self.executor.set_permission_checker(
1142
+ self.check_permission, self.name
1143
+ )
1140
1144
  exec_result = await self.executor.execute(
1141
1145
  language=code_lang,
1142
1146
  code=code_text,
@@ -1149,6 +1153,10 @@ class MainAgent(BaseAgent):
1149
1153
  elif tool_name == "command" or tool_name == "command_run":
1150
1154
  code_text = params.get("command", parms_str)
1151
1155
  if self.executor:
1156
+ # 注入权限检查器(V1 路径在 api_server 中设置,V2 路径需要在此设置)
1157
+ self.executor.set_permission_checker(
1158
+ self.check_permission, self.name
1159
+ )
1152
1160
  exec_result = await self.executor.execute(
1153
1161
  language="shell",
1154
1162
  code=code_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/main.py CHANGED
@@ -218,6 +218,10 @@ class MyAgentApp:
218
218
  max_retries=exe_cfg.max_retries,
219
219
  auto_fix=exe_cfg.auto_fix,
220
220
  max_output_length=exe_cfg.max_output_length,
221
+ execution_mode=exe_cfg.execution_mode,
222
+ sandbox_image=exe_cfg.sandbox_image,
223
+ sandbox_network=exe_cfg.sandbox_network,
224
+ sandbox_memory=exe_cfg.sandbox_memory,
221
225
  )
222
226
  self.logger.info(f"执行引擎: timeout={exe_cfg.timeout}s, auto_fix={exe_cfg.auto_fix}")
223
227
 
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.9",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {