myagent-ai 1.32.5 → 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 -49
- package/web/ui/chat/chat_main.js +52 -67
- package/web/ui/chat/flow_engine.js +2 -2
- package/web/ui/chat/groupchat.js +2 -2
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,28 +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
|
-
(target_aid,)).fetchall()
|
|
4344
|
-
else:
|
|
4345
|
-
# 其他 agent: agent_id=数字ID 或 session_id 前缀匹配(旧数据)
|
|
4346
|
-
rows = conn.execute(
|
|
4347
|
-
f"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last,
|
|
4348
|
-
MAX(CASE WHEN agent_id != ? THEN agent_id ELSE NULL END) as raw_agent_id FROM memories
|
|
4349
|
-
WHERE category = 'session' AND role != ''
|
|
4350
|
-
AND key NOT IN {_hidden}
|
|
4351
|
-
AND (agent_id = ? OR session_id LIKE ?)
|
|
4352
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4353
|
-
(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()
|
|
4354
4340
|
else:
|
|
4355
4341
|
# [v1.27.2] 无 agent 过滤时也返回 agent_id,供后台管理页面使用
|
|
4356
4342
|
rows = conn.execute(
|
|
@@ -4398,24 +4384,13 @@ window.addEventListener('beforeunload', function() {{
|
|
|
4398
4384
|
name = request.match_info["name"]
|
|
4399
4385
|
if not self.core.memory:
|
|
4400
4386
|
return web.json_response({"agent": name, "sessions": []})
|
|
4401
|
-
#
|
|
4387
|
+
# 使用数字 agent_id 精确过滤
|
|
4402
4388
|
target_aid = self.core.memory.get_agent_id(name)
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
AND (agent_id = 0 OR agent_id = ? OR session_id = 'web_default' OR session_id LIKE 'sess_%')
|
|
4409
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4410
|
-
(target_aid,)).fetchall()
|
|
4411
|
-
else:
|
|
4412
|
-
# 其他 agent: agent_id=数字ID 或 session_id 前缀匹配(旧数据)
|
|
4413
|
-
rows = self.core.memory._get_conn().execute(
|
|
4414
|
-
"""SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories
|
|
4415
|
-
WHERE category = 'session'
|
|
4416
|
-
AND (agent_id = ? OR session_id LIKE ?)
|
|
4417
|
-
GROUP BY session_id ORDER BY last DESC LIMIT 100""",
|
|
4418
|
-
(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()
|
|
4419
4394
|
sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
|
|
4420
4395
|
# 批量获取自定义会话名称
|
|
4421
4396
|
sids = [s["id"] for s in sessions]
|
|
@@ -6138,7 +6113,7 @@ window.addEventListener('beforeunload', function() {{
|
|
|
6138
6113
|
context.metadata["user_voice_text"] = voice_text # 语音输入原始文本(用于 usersays_correct)
|
|
6139
6114
|
|
|
6140
6115
|
# [v1.28] 传入正确的 agent_db_id,确保 V2 路径保存会话时使用正确的 agent_id
|
|
6141
|
-
agent_id =
|
|
6116
|
+
agent_id = 1 # 默认为全权Agent
|
|
6142
6117
|
if agent_path and self.core.memory:
|
|
6143
6118
|
agent_id = self.core.memory.get_agent_id(agent_path)
|
|
6144
6119
|
context.metadata["agent_db_id"] = agent_id
|
package/web/ui/chat/chat_main.js
CHANGED
|
@@ -150,7 +150,7 @@ function popoutChat() {
|
|
|
150
150
|
const h = Math.min(720, screen.height - 100);
|
|
151
151
|
const left = Math.round((screen.width - w) / 2);
|
|
152
152
|
const top = Math.round((screen.height - h) / 2);
|
|
153
|
-
window.open(popoutUrl, 'myagent_popout_' + (state.activeAgent || '
|
|
153
|
+
window.open(popoutUrl, 'myagent_popout_' + (state.activeAgent || '1'), 'width=' + w + ',height=' + h + ',left=' + left + ',top=' + top + ',menubar=no,toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes');
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// Override toggleAgentPanel for mobile (deferred since function is defined later)
|
|
@@ -227,11 +227,11 @@ const state = {
|
|
|
227
227
|
// ── Agent state (层级体系) ──
|
|
228
228
|
agentTree: [], // 树形结构 [{path, name, children: [...], ...}]
|
|
229
229
|
agentsFlat: [], // 扁平列表 [{path, name, parent, depth, ...}]
|
|
230
|
-
activeAgent: '
|
|
230
|
+
activeAgent: '1',
|
|
231
231
|
agentPanelOpen: true,
|
|
232
232
|
agentSessions: {}, // {agentPath: [{id, name, messages, last}]}
|
|
233
233
|
agentDetails: {}, // {agentPath: {soul, identity, model, ...}}
|
|
234
|
-
expandedNodes: new Set(['
|
|
234
|
+
expandedNodes: new Set(['1']), // 树形展开状态
|
|
235
235
|
modelsLibrary: [], // 模型库 [{id, name, provider, model, base_url, enabled, has_api_key, ...}]
|
|
236
236
|
// ── Message queue during generation ──
|
|
237
237
|
pendingMessages: [], // 待发送的消息队列 [{text, time}]
|
|
@@ -330,7 +330,7 @@ const StatePersistence = {
|
|
|
330
330
|
// 持久化当前活跃会话ID,用于页面刷新后恢复
|
|
331
331
|
if (state.activeSessionId && state.activeSessionId !== '__new__') {
|
|
332
332
|
StatePersistence.save('activeSessionId', state.activeSessionId);
|
|
333
|
-
StatePersistence.save('activeSessionAgent', state.activeAgent || '
|
|
333
|
+
StatePersistence.save('activeSessionAgent', state.activeAgent || '1');
|
|
334
334
|
}
|
|
335
335
|
// 持久化当前会话的滚动位置(立即保存,不防抖)
|
|
336
336
|
if (typeof saveScrollPosition === 'function') {
|
|
@@ -344,12 +344,12 @@ const StatePersistence = {
|
|
|
344
344
|
},
|
|
345
345
|
/** 恢复 UI 状态 */
|
|
346
346
|
restoreUIState() {
|
|
347
|
-
state.activeAgent = StatePersistence.load('activeAgent', '
|
|
347
|
+
state.activeAgent = StatePersistence.load('activeAgent', '1');
|
|
348
348
|
state.chatMode = StatePersistence.load('chatMode', 'exec');
|
|
349
349
|
state.agentPanelOpen = StatePersistence.load('agentPanelOpen', true);
|
|
350
350
|
var savedRpSections = StatePersistence.load('rpSections');
|
|
351
351
|
if (savedRpSections) { Object.assign(rpSections, savedRpSections); }
|
|
352
|
-
const savedNodes = StatePersistence.load('expandedNodes', ['
|
|
352
|
+
const savedNodes = StatePersistence.load('expandedNodes', ['1']);
|
|
353
353
|
state.expandedNodes = new Set(savedNodes);
|
|
354
354
|
// 恢复上次活跃的会话 ID,供 loadSessions() 使用
|
|
355
355
|
var savedSessionId = StatePersistence.load('activeSessionId', null);
|
|
@@ -529,24 +529,15 @@ async function initChat() {
|
|
|
529
529
|
} else if (urlAgent) {
|
|
530
530
|
var resolved = urlAgent;
|
|
531
531
|
if (!findAgentByPath(resolved)) {
|
|
532
|
-
console.warn('URL agent not found, fallback to
|
|
533
|
-
resolved =
|
|
532
|
+
console.warn('URL agent not found, fallback to master:', resolved);
|
|
533
|
+
resolved = findMasterAgentPath();
|
|
534
534
|
}
|
|
535
535
|
if (resolved !== state.activeAgent) {
|
|
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] || 'default';
|
|
543
|
-
}
|
|
544
|
-
// 新格式 sess_xxx 无法推断 agent,回退 default
|
|
545
|
-
var target = targetAgent;
|
|
546
|
-
if (!findAgentByPath(target)) {
|
|
547
|
-
console.warn('Session-inferred agent not found, fallback to default:', target);
|
|
548
|
-
target = 'default';
|
|
549
|
-
}
|
|
539
|
+
// 只有 session 没有 agent,回退 master agent
|
|
540
|
+
var target = findMasterAgentPath();
|
|
550
541
|
if (target !== state.activeAgent) {
|
|
551
542
|
selectAgent(target);
|
|
552
543
|
}
|
|
@@ -835,7 +826,7 @@ function hasTaskListChanged() {
|
|
|
835
826
|
|
|
836
827
|
async function loadTaskPlan() {
|
|
837
828
|
try {
|
|
838
|
-
var agent = state.activeAgent || '
|
|
829
|
+
var agent = state.activeAgent || '1';
|
|
839
830
|
var session = state.activeSessionId || '';
|
|
840
831
|
var url = '/api/task-plan?agent=' + encodeURIComponent(agent);
|
|
841
832
|
if (session) url += '&session=' + encodeURIComponent(session);
|
|
@@ -906,7 +897,7 @@ async function toggleTaskDone(idx) {
|
|
|
906
897
|
t.done = !t.done;
|
|
907
898
|
}
|
|
908
899
|
try {
|
|
909
|
-
var agent = state.activeAgent || '
|
|
900
|
+
var agent = state.activeAgent || '1';
|
|
910
901
|
var session = state.activeSessionId || '';
|
|
911
902
|
await api('/api/task-plan', {
|
|
912
903
|
method: 'PUT',
|
|
@@ -931,7 +922,7 @@ async function addTaskItem() {
|
|
|
931
922
|
if (!text) return;
|
|
932
923
|
input.value = '';
|
|
933
924
|
try {
|
|
934
|
-
var agent = state.activeAgent || '
|
|
925
|
+
var agent = state.activeAgent || '1';
|
|
935
926
|
var session = state.activeSessionId || '';
|
|
936
927
|
var data = await api('/api/task-plan', {
|
|
937
928
|
method: 'POST',
|
|
@@ -948,7 +939,7 @@ async function addTaskItem() {
|
|
|
948
939
|
async function deleteTaskItem(idx) {
|
|
949
940
|
if (idx < 0 || idx >= state.taskItems.length) return;
|
|
950
941
|
try {
|
|
951
|
-
var agent = state.activeAgent || '
|
|
942
|
+
var agent = state.activeAgent || '1';
|
|
952
943
|
var session = state.activeSessionId || '';
|
|
953
944
|
var url = '/api/task-plan/' + idx + '?agent=' + encodeURIComponent(agent);
|
|
954
945
|
if (session) url += '&session=' + encodeURIComponent(session);
|
|
@@ -1822,6 +1813,19 @@ function findAgentByPath(path) {
|
|
|
1822
1813
|
return state.agentsFlat.find(function(a) { return a.path === path; });
|
|
1823
1814
|
}
|
|
1824
1815
|
|
|
1816
|
+
// [v1.32.7] 查找系统级 Agent 的路径
|
|
1817
|
+
function findMasterAgentPath() {
|
|
1818
|
+
var a = state.agentsFlat.find(function(x) { return x.path === '1'; });
|
|
1819
|
+
return a ? a.path : '1';
|
|
1820
|
+
}
|
|
1821
|
+
function findHelperAgentPath() {
|
|
1822
|
+
var a = state.agentsFlat.find(function(x) { return x.path === '2'; });
|
|
1823
|
+
return a ? a.path : null;
|
|
1824
|
+
}
|
|
1825
|
+
function isSystemAgentPath(path) {
|
|
1826
|
+
return path === '1' || path === '2';
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1825
1829
|
function getActiveAgentObj() {
|
|
1826
1830
|
return findAgentByPath(state.activeAgent);
|
|
1827
1831
|
}
|
|
@@ -1832,18 +1836,15 @@ async function loadAgents() {
|
|
|
1832
1836
|
state.agentTree = treeData || [];
|
|
1833
1837
|
state.agentsFlat = flattenTree(state.agentTree, 0, null);
|
|
1834
1838
|
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
state.agentsFlat.unshift(defAgent);
|
|
1838
|
-
state.agentTree.unshift(Object.assign({}, defAgent, {children:[]}));
|
|
1839
|
-
}
|
|
1839
|
+
// 使用 findMasterAgentPath() 解析 master agent 路径
|
|
1840
|
+
var _masterPath = findMasterAgentPath();
|
|
1840
1841
|
|
|
1841
1842
|
for (var i = 0; i < state.agentsFlat.length; i++) {
|
|
1842
1843
|
state.expandedNodes.add(state.agentsFlat[i].path);
|
|
1843
1844
|
}
|
|
1844
1845
|
|
|
1845
1846
|
if (!state.activeAgent || !findAgentByPath(state.activeAgent)) {
|
|
1846
|
-
state.activeAgent =
|
|
1847
|
+
state.activeAgent = _masterPath;
|
|
1847
1848
|
}
|
|
1848
1849
|
|
|
1849
1850
|
renderAgentTree();
|
|
@@ -1852,10 +1853,10 @@ async function loadAgents() {
|
|
|
1852
1853
|
await loadSessions();
|
|
1853
1854
|
loadAllAgentSessions(); // fire-and-forget, will update recent agents
|
|
1854
1855
|
} catch (e) {
|
|
1855
|
-
var defAgent = {path:'
|
|
1856
|
+
var defAgent = {path:'1', name:'全权Agent', depth:0, parent:null, description:'全权Agent - 拥有完整权限的本地助手', avatar_emoji:'🤖', execution_mode:'local', system:true, avatar_color:getAgentColorClass('全权Agent'), session_count:0};
|
|
1856
1857
|
state.agentsFlat = [defAgent];
|
|
1857
1858
|
state.agentTree = [Object.assign({}, defAgent, {children:[]})];
|
|
1858
|
-
state.activeAgent = '
|
|
1859
|
+
state.activeAgent = '1';
|
|
1859
1860
|
renderAgentTree();
|
|
1860
1861
|
updateActiveAgentBadge();
|
|
1861
1862
|
updateExecModeUI();
|
|
@@ -1909,18 +1910,20 @@ function renderRightPanelSections() {
|
|
|
1909
1910
|
function renderMasterAgentCard() {
|
|
1910
1911
|
var el = document.getElementById('rpMasterAgent');
|
|
1911
1912
|
if (!el) return;
|
|
1912
|
-
|
|
1913
|
-
var
|
|
1913
|
+
// 使用 findMasterAgentPath() 获取 master agent 路径
|
|
1914
|
+
var masterPath = findMasterAgentPath();
|
|
1915
|
+
var agent = findAgentByPath(masterPath);
|
|
1916
|
+
var isActive = state.activeAgent === masterPath;
|
|
1914
1917
|
var name = agent ? agent.name : '全权Agent';
|
|
1915
1918
|
var emoji = agent ? (agent.avatar_emoji || '🛡️') : '🛡️';
|
|
1916
1919
|
var desc = agent ? (agent.description || '拥有完整权限的本地助手') : '拥有完整权限的本地助手';
|
|
1917
1920
|
var color = agent ? (agent.avatar_color || 'linear-gradient(135deg,#6366f1,#8b5cf6)') : 'linear-gradient(135deg,#6366f1,#8b5cf6)';
|
|
1918
1921
|
var bgStyle = color.includes('gradient') ? 'background:' + color : '';
|
|
1919
|
-
var bgClass = color.includes('gradient') ? '' : getAgentColorClass(
|
|
1922
|
+
var bgClass = color.includes('gradient') ? '' : getAgentColorClass(masterPath);
|
|
1920
1923
|
// [v1.20.9] 修复: avatar_image 不为空时显示图片,onerror 回退到 emoji
|
|
1921
1924
|
var avatarContent = (agent && agent.avatar_image) ? '<img src="' + escapeHtml(agent.avatar_image) + '" style="width:100%;height:100%;object-fit:cover;border-radius:12px" onerror="this.outerHTML=\'' + escapeHtml(emoji) + '\'">' : emoji;
|
|
1922
1925
|
|
|
1923
|
-
el.innerHTML = '<div class="rp-master-card ' + (isActive ? 'active' : '') + '" onclick="selectAgent(\'
|
|
1926
|
+
el.innerHTML = '<div class="rp-master-card ' + (isActive ? 'active' : '') + '" onclick="selectAgent(\'' + escapeHtml(masterPath) + '\')">'
|
|
1924
1927
|
+ '<div class="rp-master-avatar ' + bgClass + '" style="' + bgStyle + '">' + avatarContent + '</div>'
|
|
1925
1928
|
+ '<div class="rp-master-info">'
|
|
1926
1929
|
+ '<div class="rp-master-name">' + escapeHtml(name) + '</div>'
|
|
@@ -1931,8 +1934,11 @@ function renderMasterAgentCard() {
|
|
|
1931
1934
|
function renderHelperAgentCard() {
|
|
1932
1935
|
var el = document.getElementById('rpHelperAgent');
|
|
1933
1936
|
if (!el) return;
|
|
1934
|
-
|
|
1935
|
-
var
|
|
1937
|
+
// 使用 findHelperAgentPath() 获取 helper agent 路径
|
|
1938
|
+
var helperPath = findHelperAgentPath();
|
|
1939
|
+
if (!helperPath) { el.innerHTML = ''; return; } // 无配置助手则不渲染
|
|
1940
|
+
var agent = findAgentByPath(helperPath);
|
|
1941
|
+
var isActive = state.activeAgent === helperPath;
|
|
1936
1942
|
var name = agent ? agent.name : '配置助手';
|
|
1937
1943
|
var emoji = agent ? (agent.avatar_emoji || '🛡️') : '🛡️';
|
|
1938
1944
|
var desc = agent ? (agent.description || '智能配置助手') : '智能配置助手';
|
|
@@ -1945,7 +1951,7 @@ function renderHelperAgentCard() {
|
|
|
1945
1951
|
avatarContent = emoji;
|
|
1946
1952
|
}
|
|
1947
1953
|
|
|
1948
|
-
el.innerHTML = '<div class="rp-helper-card ' + (isActive ? 'active' : '') + '" onclick="selectAgent(\'
|
|
1954
|
+
el.innerHTML = '<div class="rp-helper-card ' + (isActive ? 'active' : '') + '" onclick="selectAgent(\'' + escapeHtml(helperPath) + '\')">'
|
|
1949
1955
|
+ '<div class="rp-helper-avatar" style="' + (avatarImage ? 'background:transparent' : '') + '">' + avatarContent + '</div>'
|
|
1950
1956
|
+ '<div class="rp-master-info">'
|
|
1951
1957
|
+ '<div class="rp-master-name" style="font-size:13px">' + escapeHtml(name) + '</div>'
|
|
@@ -1962,7 +1968,7 @@ async function renderRecentAgents() {
|
|
|
1962
1968
|
var recentAgents = [];
|
|
1963
1969
|
|
|
1964
1970
|
for (var key in state.agentSessions) {
|
|
1965
|
-
if (key
|
|
1971
|
+
if (isSystemAgentPath(key)) continue;
|
|
1966
1972
|
var sessions = state.agentSessions[key];
|
|
1967
1973
|
if (sessions && sessions.length > 0) {
|
|
1968
1974
|
var agent = findAgentByPath(key);
|
|
@@ -2168,10 +2174,10 @@ function quickChatAgent(agentPath) {
|
|
|
2168
2174
|
}
|
|
2169
2175
|
|
|
2170
2176
|
async function selectAgent(agentPath) {
|
|
2171
|
-
// 安全校验:agent 必须在已加载的列表中存在,否则回退
|
|
2177
|
+
// 安全校验:agent 必须在已加载的列表中存在,否则回退 master agent
|
|
2172
2178
|
if (!findAgentByPath(agentPath)) {
|
|
2173
|
-
console.warn('selectAgent: agent not found, fallback to
|
|
2174
|
-
agentPath =
|
|
2179
|
+
console.warn('selectAgent: agent not found, fallback to master:', agentPath);
|
|
2180
|
+
agentPath = findMasterAgentPath();
|
|
2175
2181
|
}
|
|
2176
2182
|
// 从群聊视图切换回个人聊天视图
|
|
2177
2183
|
if (currentView === 'group') {
|
|
@@ -2575,7 +2581,7 @@ async function saveAgentModal(editPath, parentPath) {
|
|
|
2575
2581
|
}
|
|
2576
2582
|
|
|
2577
2583
|
async function deleteAgent(agentPath) {
|
|
2578
|
-
if (agentPath ===
|
|
2584
|
+
if (agentPath === findMasterAgentPath()) { toast('不能删除默认 Agent', 'error'); return; }
|
|
2579
2585
|
var msg = '确定删除 Agent "' + agentPath + '" 吗?\n\n删除后将同时清理:\n 📁 工作目录及所有文件\n 💬 该 Agent 的所有会话历史\n 🧠 相关记忆数据\n 🔗 所有子 Agent\n\n⚠️ 此操作不可撤销!';
|
|
2580
2586
|
if (!confirm(msg)) return;
|
|
2581
2587
|
try {
|
|
@@ -2583,7 +2589,7 @@ async function deleteAgent(agentPath) {
|
|
|
2583
2589
|
toast('Agent 已删除', 'success');
|
|
2584
2590
|
closeAgentModal();
|
|
2585
2591
|
if (state.activeAgent === agentPath || state.activeAgent.startsWith(agentPath + '/')) {
|
|
2586
|
-
state.activeAgent =
|
|
2592
|
+
state.activeAgent = findMasterAgentPath();
|
|
2587
2593
|
}
|
|
2588
2594
|
await loadAgents();
|
|
2589
2595
|
} catch (e) {
|
|
@@ -2659,34 +2665,12 @@ async function loadSessions() {
|
|
|
2659
2665
|
if (urlSession && state.sessions.some(s => s.id === urlSession)) {
|
|
2660
2666
|
// URL 指定了有效的 session ID,直接选中(刷新恢复)
|
|
2661
2667
|
targetSessionId = urlSession;
|
|
2662
|
-
} else if (urlSession) {
|
|
2663
|
-
// [v1.23.24] 前缀匹配 fallback:前端生成的临时 ID 与后端 canonical ID 可能不同
|
|
2664
|
-
// 例如前端 "default_web_20250101120000" 后端实际为 "default_web_20250101120000_a1b2c3"
|
|
2665
|
-
var prefixMatch = state.sessions.find(function(s) {
|
|
2666
|
-
return s.id.startsWith(urlSession) || urlSession.startsWith(s.id);
|
|
2667
|
-
});
|
|
2668
|
-
if (prefixMatch) {
|
|
2669
|
-
targetSessionId = prefixMatch.id;
|
|
2670
|
-
// 更新 URL 为 canonical ID,避免下次刷新再走 fallback
|
|
2671
|
-
try {
|
|
2672
|
-
var _fixUrl = new URL(window.location.href);
|
|
2673
|
-
_fixUrl.searchParams.set('s', UrlCodec.encode(prefixMatch.id));
|
|
2674
|
-
window.history.replaceState({}, '', _fixUrl.toString());
|
|
2675
|
-
} catch (_) {}
|
|
2676
|
-
}
|
|
2677
2668
|
}
|
|
2678
2669
|
if (!targetSessionId && state._pendingSessionRestore && state.sessions.some(s => s.id === state._pendingSessionRestore)) {
|
|
2679
2670
|
// 从 localStorage 恢复的 session(beforeunload 触发的保存)
|
|
2680
2671
|
targetSessionId = state._pendingSessionRestore;
|
|
2681
2672
|
state._pendingSessionRestore = null; // 清除,防止重复恢复
|
|
2682
2673
|
} else if (!targetSessionId && state._pendingSessionRestore) {
|
|
2683
|
-
// [v1.23.24] localStorage 恢复的 ID 也不匹配,尝试前缀匹配
|
|
2684
|
-
var lsPrefixMatch = state.sessions.find(function(s) {
|
|
2685
|
-
return s.id.startsWith(state._pendingSessionRestore) || state._pendingSessionRestore.startsWith(s.id);
|
|
2686
|
-
});
|
|
2687
|
-
if (lsPrefixMatch) {
|
|
2688
|
-
targetSessionId = lsPrefixMatch.id;
|
|
2689
|
-
}
|
|
2690
2674
|
state._pendingSessionRestore = null;
|
|
2691
2675
|
}
|
|
2692
2676
|
if (!targetSessionId && !state.activeSessionId && state.sessions.length > 0) {
|
|
@@ -5120,7 +5104,8 @@ function skipSetup() {
|
|
|
5120
5104
|
StatePersistence.markSetupDone();
|
|
5121
5105
|
try { api('/api/setup/complete', { method: 'POST' }); } catch(e) {}
|
|
5122
5106
|
// 自动切换到配置助手 Agent
|
|
5123
|
-
|
|
5107
|
+
var _helperPath = findHelperAgentPath();
|
|
5108
|
+
if (_helperPath) selectAgent(_helperPath);
|
|
5124
5109
|
}
|
|
5125
5110
|
|
|
5126
5111
|
function renderSetupDots() {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// ── 输入框草稿持久化(按 agent + session 维度保存,刷新页面不丢失) ──
|
|
8
8
|
var _draftTimer = null;
|
|
9
9
|
function _draftKey() {
|
|
10
|
-
return 'myagent_draft_' + (state.activeAgent || '
|
|
10
|
+
return 'myagent_draft_' + (state.activeAgent || '1') + '_' + (state.activeSessionId || '__new__');
|
|
11
11
|
}
|
|
12
12
|
function saveDraft() {
|
|
13
13
|
if (_draftTimer) clearTimeout(_draftTimer);
|
|
@@ -128,7 +128,7 @@ async function confirmLargeTextAction() {
|
|
|
128
128
|
var text = _pendingLargeText;
|
|
129
129
|
if (text === null || idx === null) return;
|
|
130
130
|
|
|
131
|
-
var agentPath = state.activeAgent || '
|
|
131
|
+
var agentPath = state.activeAgent || '1';
|
|
132
132
|
|
|
133
133
|
if (idx === 0) {
|
|
134
134
|
// 导入知识库
|
package/web/ui/chat/groupchat.js
CHANGED
|
@@ -346,7 +346,7 @@ function exitGroupChat() {
|
|
|
346
346
|
groupMessages = [];
|
|
347
347
|
// [v1.23.81] 清除群聊 ?g= session URL,恢复普通聊天 URL
|
|
348
348
|
var cleanUrl = '/ui/chat/chat_container.html';
|
|
349
|
-
if (typeof state !== 'undefined' && state.activeAgent && state.activeAgent !== '
|
|
349
|
+
if (typeof state !== 'undefined' && state.activeAgent && state.activeAgent !== (typeof findMasterAgentPath === 'function' ? findMasterAgentPath() : '1')) {
|
|
350
350
|
cleanUrl += '?a=' + encodeURIComponent(state.activeAgent);
|
|
351
351
|
}
|
|
352
352
|
if (typeof state !== 'undefined' && state.activeSessionId && state.activeSessionId !== '__new__') {
|
|
@@ -456,7 +456,7 @@ function startPrivateChatFromGroup(agentPath) {
|
|
|
456
456
|
StatePersistence.remove('currentGroupId');
|
|
457
457
|
// 清除群聊 URL 中的 ?g= 参数
|
|
458
458
|
var cleanUrl = '/ui/chat/chat_container.html';
|
|
459
|
-
if (typeof state !== 'undefined' && agentPath && agentPath !== '
|
|
459
|
+
if (typeof state !== 'undefined' && agentPath && agentPath !== (typeof findMasterAgentPath === 'function' ? findMasterAgentPath() : '1')) {
|
|
460
460
|
cleanUrl += '?a=' + encodeURIComponent(agentPath);
|
|
461
461
|
}
|
|
462
462
|
window.history.replaceState({}, '', cleanUrl);
|