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.
- package/agents/__pycache__/main_agent.cpython-312.pyc +0 -0
- package/agents/__pycache__/memory_agent.cpython-312.pyc +0 -0
- package/agents/main_agent.py +25 -17
- package/agents/memory_agent.py +2 -2
- package/config.py +0 -5
- package/core/__pycache__/context_builder.cpython-312.pyc +0 -0
- package/main.py +4 -0
- package/memory/__pycache__/manager.cpython-312.pyc +0 -0
- package/memory/manager.py +22 -129
- package/package.json +1 -1
- package/web/__pycache__/api_server.cpython-312.pyc +0 -0
- package/web/api_server.py +40 -27
- package/web/ui/chat/chat.css +21 -3
- package/web/ui/chat/chat_main.js +182 -35
- package/web/ui/chat/flow_engine.js +90 -67
- package/web/ui/chat/middle_chat.html +1 -1
- package/web/ui/index.html +18 -22
|
Binary file
|
|
Binary file
|
package/agents/main_agent.py
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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,
|
package/agents/memory_agent.py
CHANGED
|
@@ -116,7 +116,7 @@ class MemoryAgent(BaseAgent):
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
# 修剪旧消息
|
|
119
|
-
max_msgs = self.config.memory.
|
|
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.
|
|
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
|
Binary file
|
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
|
|
|
Binary file
|
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
|
-
|
|
256
|
-
|
|
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
|
-
"""
|
|
288
|
+
"""获取对话历史(session 分类中 role 非空的条目)"""
|
|
369
289
|
conn = self._get_conn()
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
-
|
|
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
|
-
|
|
539
|
-
|
|
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
|
|
538
|
+
def get_global_memories(self, session_id="global", key="", limit=50) -> List[MemoryEntry]:
|
|
637
539
|
"""获取全局记忆"""
|
|
638
540
|
conn = self._get_conn()
|
|
639
|
-
|
|
640
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
816
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1009
|
-
|
|
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
|
Binary file
|