myagent-ai 1.32.6 → 1.32.7
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/main_agent.py +1 -1
- package/memory/manager.py +3 -3
- package/package.json +1 -1
- package/web/api_server.py +24 -51
- package/web/ui/chat/chat_main.js +10 -51
package/agents/main_agent.py
CHANGED
|
@@ -221,7 +221,7 @@ class MainAgent(BaseAgent):
|
|
|
221
221
|
try:
|
|
222
222
|
self.agent_id = self.memory.get_agent_id(self.name)
|
|
223
223
|
except Exception:
|
|
224
|
-
self.agent_id =
|
|
224
|
+
self.agent_id = 1
|
|
225
225
|
|
|
226
226
|
def init_context_builder(self, memory_manager=None, skill_registry=None, knowledge_base_dir=None, context_window=None):
|
|
227
227
|
"""初始化 Context Builder(在系统启动后调用,注入依赖)"""
|
package/memory/manager.py
CHANGED
|
@@ -147,14 +147,14 @@ class MemoryManager:
|
|
|
147
147
|
from datetime import datetime as _dt
|
|
148
148
|
from core.utils import get_config_tz
|
|
149
149
|
now = _dt.now(get_config_tz()).strftime("%Y-%m-%d %H:%M:%S")
|
|
150
|
-
conn.execute("INSERT OR IGNORE INTO agents (id, name, created_at) VALUES (1, '
|
|
150
|
+
conn.execute("INSERT OR IGNORE INTO agents (id, name, created_at) VALUES (1, '1', ?)", (now,))
|
|
151
151
|
|
|
152
152
|
# 创建 memories 表
|
|
153
153
|
conn.executescript("""
|
|
154
154
|
CREATE TABLE IF NOT EXISTS memories (
|
|
155
155
|
id TEXT PRIMARY KEY,
|
|
156
156
|
session_id TEXT NOT NULL,
|
|
157
|
-
agent_id INTEGER NOT NULL DEFAULT
|
|
157
|
+
agent_id INTEGER NOT NULL DEFAULT 1,
|
|
158
158
|
category TEXT NOT NULL,
|
|
159
159
|
key TEXT DEFAULT '',
|
|
160
160
|
content TEXT DEFAULT '',
|
|
@@ -333,7 +333,7 @@ class MemoryManager:
|
|
|
333
333
|
# 会话记忆 (session) — 对话上下文 + 任务进度
|
|
334
334
|
# ==========================================================================
|
|
335
335
|
|
|
336
|
-
def add_session(self, session_id, agent_id=
|
|
336
|
+
def add_session(self, session_id, agent_id=1, role="", content="", key="", importance=0.5, metadata=None) -> str:
|
|
337
337
|
"""添加会话记忆。内容不包含时间前缀,时间仅存于 created_at 和 metadata。"""
|
|
338
338
|
from datetime import datetime as _dt
|
|
339
339
|
from core.utils import get_config_tz
|
package/package.json
CHANGED
package/web/api_server.py
CHANGED
|
@@ -1896,8 +1896,7 @@ window.addEventListener('beforeunload', function() {{
|
|
|
1896
1896
|
agent_path = data.get("agent_path", agent_name)
|
|
1897
1897
|
# 获取数字 agent_id
|
|
1898
1898
|
agent_id = self.core.memory.get_agent_id(agent_path)
|
|
1899
|
-
|
|
1900
|
-
session_id = data.get("sid", "") or data.get("session_id", "") or "web_default"
|
|
1899
|
+
session_id = data.get("sid", "") or data.get("session_id", "")
|
|
1901
1900
|
chat_mode = data.get("mode", "") # "exec" = 执行模式
|
|
1902
1901
|
escalated = data.get("escalated", False) # 临时提权到 local
|
|
1903
1902
|
|
|
@@ -2056,8 +2055,7 @@ window.addEventListener('beforeunload', function() {{
|
|
|
2056
2055
|
return web.Response(text="data: " + json.dumps({"error": "message is required"}) + "\n\n", content_type="text/event-stream")
|
|
2057
2056
|
|
|
2058
2057
|
agent_path = data.get("agent_path", data.get("agent_name", "1")) or "1"
|
|
2059
|
-
|
|
2060
|
-
session_id = data.get("sid", "") or data.get("session_id", "") or "web_default"
|
|
2058
|
+
session_id = data.get("sid", "") or data.get("session_id", "")
|
|
2061
2059
|
chat_mode = data.get("mode", "")
|
|
2062
2060
|
escalated = data.get("escalated", False)
|
|
2063
2061
|
voice_text = data.get("voice_text", "").strip() # 语音转文字原始文本(用于 usersays_correct)
|
|
@@ -2449,8 +2447,7 @@ window.addEventListener('beforeunload', function() {{
|
|
|
2449
2447
|
return web.json_response({"error": "message is required"}, status=400)
|
|
2450
2448
|
|
|
2451
2449
|
agent_path = data.get("agent_path", "1") or "1"
|
|
2452
|
-
|
|
2453
|
-
session_id = data.get("sid", "") or data.get("session_id", "web_default")
|
|
2450
|
+
session_id = data.get("sid", "") or data.get("session_id", "")
|
|
2454
2451
|
choice = data.get("choice", "queue") # "continue" (插入后继续) 或 "queue" (排队)
|
|
2455
2452
|
|
|
2456
2453
|
# 检查会话是否正在运行
|
|
@@ -3834,12 +3831,12 @@ window.addEventListener('beforeunload', function() {{
|
|
|
3834
3831
|
# 清理该 Agent 相关的会话和记忆数据
|
|
3835
3832
|
if self.core.memory:
|
|
3836
3833
|
try:
|
|
3837
|
-
#
|
|
3834
|
+
# 删除该 agent 的所有会话(通过 agent_id 精确匹配)
|
|
3838
3835
|
conn = self.core.memory._get_conn()
|
|
3839
|
-
|
|
3836
|
+
target_aid = self.core.memory.get_agent_id(path)
|
|
3840
3837
|
rows = conn.execute(
|
|
3841
|
-
"SELECT DISTINCT session_id FROM memories WHERE
|
|
3842
|
-
(
|
|
3838
|
+
"SELECT DISTINCT session_id FROM memories WHERE agent_id = ?",
|
|
3839
|
+
(target_aid,),
|
|
3843
3840
|
).fetchall()
|
|
3844
3841
|
for row in rows:
|
|
3845
3842
|
sid = row["session_id"]
|
|
@@ -4329,29 +4326,17 @@ window.addEventListener('beforeunload', function() {{
|
|
|
4329
4326
|
_hidden = '(' + ','.join(["'llm_output'", "'llm_input'", "'tool_result_raw'", "'conversation_insight'"]) + ')'
|
|
4330
4327
|
# 只统计用户可见的消息数(排除 llm_output 和 conversation_insight)
|
|
4331
4328
|
if agent:
|
|
4332
|
-
#
|
|
4329
|
+
# 将 agent 路径转为数字 ID,精确过滤
|
|
4333
4330
|
target_aid = self.core.memory.get_agent_id(agent) if agent else 0
|
|
4334
|
-
#
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4344
|
-
(target_aid,)).fetchall()
|
|
4345
|
-
else:
|
|
4346
|
-
# 其他 agent: agent_id=数字ID 或 session_id 前缀匹配(旧数据)
|
|
4347
|
-
rows = conn.execute(
|
|
4348
|
-
f"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last,
|
|
4349
|
-
MAX(CASE WHEN agent_id != ? THEN agent_id ELSE NULL END) as raw_agent_id FROM memories
|
|
4350
|
-
WHERE category = 'session' AND role != ''
|
|
4351
|
-
AND key NOT IN {_hidden}
|
|
4352
|
-
AND (agent_id = ? OR session_id LIKE ?)
|
|
4353
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4354
|
-
(target_aid, target_aid, f"{agent}_%")).fetchall()
|
|
4331
|
+
# 统一使用 agent_id 精确匹配,不再兼容旧数据
|
|
4332
|
+
rows = conn.execute(
|
|
4333
|
+
f"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last,
|
|
4334
|
+
MAX(CASE WHEN agent_id != ? THEN agent_id ELSE NULL END) as raw_agent_id FROM memories
|
|
4335
|
+
WHERE category = 'session' AND role != ''
|
|
4336
|
+
AND key NOT IN {_hidden}
|
|
4337
|
+
AND agent_id = ?
|
|
4338
|
+
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4339
|
+
(target_aid, target_aid)).fetchall()
|
|
4355
4340
|
else:
|
|
4356
4341
|
# [v1.27.2] 无 agent 过滤时也返回 agent_id,供后台管理页面使用
|
|
4357
4342
|
rows = conn.execute(
|
|
@@ -4399,25 +4384,13 @@ window.addEventListener('beforeunload', function() {{
|
|
|
4399
4384
|
name = request.match_info["name"]
|
|
4400
4385
|
if not self.core.memory:
|
|
4401
4386
|
return web.json_response({"agent": name, "sessions": []})
|
|
4402
|
-
#
|
|
4387
|
+
# 使用数字 agent_id 精确过滤
|
|
4403
4388
|
target_aid = self.core.memory.get_agent_id(name)
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
WHERE category = 'session'
|
|
4410
|
-
AND (agent_id = 0 OR agent_id = ? OR session_id = 'web_default' OR session_id LIKE 'sess_%')
|
|
4411
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4412
|
-
(target_aid,)).fetchall()
|
|
4413
|
-
else:
|
|
4414
|
-
# 其他 agent: agent_id=数字ID 或 session_id 前缀匹配(旧数据)
|
|
4415
|
-
rows = self.core.memory._get_conn().execute(
|
|
4416
|
-
"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories
|
|
4417
|
-
WHERE category = 'session'
|
|
4418
|
-
AND (agent_id = ? OR session_id LIKE ?)
|
|
4419
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4420
|
-
(target_aid, f"{name}_%")).fetchall()
|
|
4389
|
+
rows = self.core.memory._get_conn().execute(
|
|
4390
|
+
"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories
|
|
4391
|
+
WHERE category = 'session' AND agent_id = ?
|
|
4392
|
+
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4393
|
+
(target_aid,)).fetchall()
|
|
4421
4394
|
sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
|
|
4422
4395
|
# 批量获取自定义会话名称
|
|
4423
4396
|
sids = [s["id"] for s in sessions]
|
|
@@ -6140,7 +6113,7 @@ window.addEventListener('beforeunload', function() {{
|
|
|
6140
6113
|
context.metadata["user_voice_text"] = voice_text # 语音输入原始文本(用于 usersays_correct)
|
|
6141
6114
|
|
|
6142
6115
|
# [v1.28] 传入正确的 agent_db_id,确保 V2 路径保存会话时使用正确的 agent_id
|
|
6143
|
-
agent_id =
|
|
6116
|
+
agent_id = 1 # 默认为全权Agent
|
|
6144
6117
|
if agent_path and self.core.memory:
|
|
6145
6118
|
agent_id = self.core.memory.get_agent_id(agent_path)
|
|
6146
6119
|
context.metadata["agent_db_id"] = agent_id
|
package/web/ui/chat/chat_main.js
CHANGED
|
@@ -536,17 +536,8 @@ async function initChat() {
|
|
|
536
536
|
selectAgent(resolved);
|
|
537
537
|
}
|
|
538
538
|
} else if (urlSession) {
|
|
539
|
-
// 只有 session 没有 agent
|
|
540
|
-
var
|
|
541
|
-
if (urlSession.indexOf('_web_') >= 0) {
|
|
542
|
-
targetAgent = urlSession.split('_web_')[0] || findMasterAgentPath();
|
|
543
|
-
}
|
|
544
|
-
// 新格式 sess_xxx 无法推断 agent,回退 master
|
|
545
|
-
var target = targetAgent;
|
|
546
|
-
if (!findAgentByPath(target)) {
|
|
547
|
-
console.warn('Session-inferred agent not found, fallback to master:', target);
|
|
548
|
-
target = findMasterAgentPath();
|
|
549
|
-
}
|
|
539
|
+
// 只有 session 没有 agent,回退 master agent
|
|
540
|
+
var target = findMasterAgentPath();
|
|
550
541
|
if (target !== state.activeAgent) {
|
|
551
542
|
selectAgent(target);
|
|
552
543
|
}
|
|
@@ -1822,26 +1813,17 @@ function findAgentByPath(path) {
|
|
|
1822
1813
|
return state.agentsFlat.find(function(a) { return a.path === path; });
|
|
1823
1814
|
}
|
|
1824
1815
|
|
|
1825
|
-
// [v1.32.
|
|
1816
|
+
// [v1.32.7] 查找系统级 Agent 的路径
|
|
1826
1817
|
function findMasterAgentPath() {
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|| state.agentsFlat.find(function(x) { return x.path === 'default'; })
|
|
1830
|
-
|| state.agentsFlat.find(function(x) { return x.system && x.name === '全权Agent'; })
|
|
1831
|
-
|| state.agentsFlat.find(function(x) { return x.system; });
|
|
1832
|
-
return a ? a.path : 'default';
|
|
1818
|
+
var a = state.agentsFlat.find(function(x) { return x.path === '1'; });
|
|
1819
|
+
return a ? a.path : '1';
|
|
1833
1820
|
}
|
|
1834
1821
|
function findHelperAgentPath() {
|
|
1835
|
-
var a = state.agentsFlat.find(function(x) { return x.path === '2'; })
|
|
1836
|
-
|| state.agentsFlat.find(function(x) { return x.path === '配置助手'; })
|
|
1837
|
-
|| state.agentsFlat.find(function(x) { return x.system && x.name === '配置助手'; })
|
|
1838
|
-
|| null;
|
|
1822
|
+
var a = state.agentsFlat.find(function(x) { return x.path === '2'; });
|
|
1839
1823
|
return a ? a.path : null;
|
|
1840
1824
|
}
|
|
1841
1825
|
function isSystemAgentPath(path) {
|
|
1842
|
-
|
|
1843
|
-
var hp = findHelperAgentPath();
|
|
1844
|
-
return path === mp || (hp !== null && path === hp);
|
|
1826
|
+
return path === '1' || path === '2';
|
|
1845
1827
|
}
|
|
1846
1828
|
|
|
1847
1829
|
function getActiveAgentObj() {
|
|
@@ -1854,8 +1836,7 @@ async function loadAgents() {
|
|
|
1854
1836
|
state.agentTree = treeData || [];
|
|
1855
1837
|
state.agentsFlat = flattenTree(state.agentTree, 0, null);
|
|
1856
1838
|
|
|
1857
|
-
//
|
|
1858
|
-
// 而是依赖 findMasterAgentPath() 来正确解析 master agent 路径
|
|
1839
|
+
// 使用 findMasterAgentPath() 解析 master agent 路径
|
|
1859
1840
|
var _masterPath = findMasterAgentPath();
|
|
1860
1841
|
|
|
1861
1842
|
for (var i = 0; i < state.agentsFlat.length; i++) {
|
|
@@ -1929,7 +1910,7 @@ function renderRightPanelSections() {
|
|
|
1929
1910
|
function renderMasterAgentCard() {
|
|
1930
1911
|
var el = document.getElementById('rpMasterAgent');
|
|
1931
1912
|
if (!el) return;
|
|
1932
|
-
//
|
|
1913
|
+
// 使用 findMasterAgentPath() 获取 master agent 路径
|
|
1933
1914
|
var masterPath = findMasterAgentPath();
|
|
1934
1915
|
var agent = findAgentByPath(masterPath);
|
|
1935
1916
|
var isActive = state.activeAgent === masterPath;
|
|
@@ -1953,7 +1934,7 @@ function renderMasterAgentCard() {
|
|
|
1953
1934
|
function renderHelperAgentCard() {
|
|
1954
1935
|
var el = document.getElementById('rpHelperAgent');
|
|
1955
1936
|
if (!el) return;
|
|
1956
|
-
//
|
|
1937
|
+
// 使用 findHelperAgentPath() 获取 helper agent 路径
|
|
1957
1938
|
var helperPath = findHelperAgentPath();
|
|
1958
1939
|
if (!helperPath) { el.innerHTML = ''; return; } // 无配置助手则不渲染
|
|
1959
1940
|
var agent = findAgentByPath(helperPath);
|
|
@@ -2684,34 +2665,12 @@ async function loadSessions() {
|
|
|
2684
2665
|
if (urlSession && state.sessions.some(s => s.id === urlSession)) {
|
|
2685
2666
|
// URL 指定了有效的 session ID,直接选中(刷新恢复)
|
|
2686
2667
|
targetSessionId = urlSession;
|
|
2687
|
-
} else if (urlSession) {
|
|
2688
|
-
// [v1.23.24] 前缀匹配 fallback:前端生成的临时 ID 与后端 canonical ID 可能不同
|
|
2689
|
-
// 例如前端 "default_web_20250101120000" 后端实际为 "default_web_20250101120000_a1b2c3"
|
|
2690
|
-
var prefixMatch = state.sessions.find(function(s) {
|
|
2691
|
-
return s.id.startsWith(urlSession) || urlSession.startsWith(s.id);
|
|
2692
|
-
});
|
|
2693
|
-
if (prefixMatch) {
|
|
2694
|
-
targetSessionId = prefixMatch.id;
|
|
2695
|
-
// 更新 URL 为 canonical ID,避免下次刷新再走 fallback
|
|
2696
|
-
try {
|
|
2697
|
-
var _fixUrl = new URL(window.location.href);
|
|
2698
|
-
_fixUrl.searchParams.set('s', UrlCodec.encode(prefixMatch.id));
|
|
2699
|
-
window.history.replaceState({}, '', _fixUrl.toString());
|
|
2700
|
-
} catch (_) {}
|
|
2701
|
-
}
|
|
2702
2668
|
}
|
|
2703
2669
|
if (!targetSessionId && state._pendingSessionRestore && state.sessions.some(s => s.id === state._pendingSessionRestore)) {
|
|
2704
2670
|
// 从 localStorage 恢复的 session(beforeunload 触发的保存)
|
|
2705
2671
|
targetSessionId = state._pendingSessionRestore;
|
|
2706
2672
|
state._pendingSessionRestore = null; // 清除,防止重复恢复
|
|
2707
2673
|
} else if (!targetSessionId && state._pendingSessionRestore) {
|
|
2708
|
-
// [v1.23.24] localStorage 恢复的 ID 也不匹配,尝试前缀匹配
|
|
2709
|
-
var lsPrefixMatch = state.sessions.find(function(s) {
|
|
2710
|
-
return s.id.startsWith(state._pendingSessionRestore) || state._pendingSessionRestore.startsWith(s.id);
|
|
2711
|
-
});
|
|
2712
|
-
if (lsPrefixMatch) {
|
|
2713
|
-
targetSessionId = lsPrefixMatch.id;
|
|
2714
|
-
}
|
|
2715
2674
|
state._pendingSessionRestore = null;
|
|
2716
2675
|
}
|
|
2717
2676
|
if (!targetSessionId && !state.activeSessionId && state.sessions.length > 0) {
|