myagent-ai 1.32.7 → 1.32.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/memory/manager.py CHANGED
@@ -35,8 +35,8 @@ logger = get_logger("myagent.memory")
35
35
  class MemoryEntry:
36
36
  """记忆条目"""
37
37
  id: str = field(default_factory=lambda: generate_id("mem"))
38
- session_id: str = "default"
39
- agent_id: int = 0 # 所属agent ID(数字ID,从1开始,0表示未分配)
38
+ session_id: str = ""
39
+ agent_id: int = 1 # 所属agent ID(数字ID,从1开始,1=全权Agent)
40
40
  category: str = "session" # session | global
41
41
  key: str = "" # 检索键/标签
42
42
  content: str = "" # 记忆内容
@@ -66,7 +66,7 @@ class MemoryEntry:
66
66
  return cls(
67
67
  id=row["id"],
68
68
  session_id=row["session_id"],
69
- agent_id=int(dict(row).get("agent_id", 0) or 0),
69
+ agent_id=int(dict(row).get("agent_id", 1) or 1),
70
70
  category=row["category"],
71
71
  key=row["key"],
72
72
  content=row["content"],
@@ -207,7 +207,8 @@ class MemoryManager:
207
207
  return cursor.lastrowid
208
208
  except Exception as e:
209
209
  logger.error(f"获取 agent ID 失败: {e}")
210
- return 0
210
+ # 返回 1 作为兜底(全权Agent),避免 agent_id=0 导致数据归属不明
211
+ return 1
211
212
 
212
213
  def register_agent(self, agent_name: str) -> int:
213
214
  """注册新 agent,返回分配的 ID"""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.32.7",
3
+ "version": "1.32.9",
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
@@ -2189,7 +2189,7 @@ window.addEventListener('beforeunload', function() {{
2189
2189
  """后台任务:即使 SSE 断开也完整执行并保存结果"""
2190
2190
  logger.info(f"[{session_id}] _run_stream_task 开始执行")
2191
2191
  # [v1.32.2] 安全修复: 定义 agent_id,避免 except 块中引用时 NameError
2192
- _stream_agent_id = self.core.memory.get_agent_id(agent_path) if self.core.memory and agent_path else 0
2192
+ _stream_agent_id = self.core.memory.get_agent_id(agent_path) if self.core.memory and agent_path else 1
2193
2193
  try:
2194
2194
  agent_cfg = self._read_agent_config(agent_path)
2195
2195
  model_chain = self._build_model_chain(agent_cfg, agent_path)
@@ -3515,7 +3515,7 @@ window.addEventListener('beforeunload', function() {{
3515
3515
  """GET /api/agents - 返回扁平 agent 列表(系统 agent 排在最前)"""
3516
3516
  await self._ensure_agents_initialized()
3517
3517
  agents = self._scan_agents_flat()
3518
- # 统计会话数
3518
+ # 统计会话数 + 附加数字 agent_id
3519
3519
  if self.core.memory:
3520
3520
  rows = self.core.memory._get_conn().execute(
3521
3521
  "SELECT session_id, COUNT(*) as cnt FROM memories "
@@ -3527,6 +3527,7 @@ window.addEventListener('beforeunload', function() {{
3527
3527
  session_counts[ap] = session_counts.get(ap, 0) + r["cnt"]
3528
3528
  for a in agents:
3529
3529
  a["session_count"] = session_counts.get(a["path"], 0)
3530
+ a["aid"] = self.core.memory.get_agent_id(a["path"])
3530
3531
  # 系统 agent 排在最前
3531
3532
  agents.sort(key=lambda a: (0 if a.get("system") else 1, a.get("path", "")))
3532
3533
  return web.json_response(agents)
@@ -4327,21 +4328,21 @@ window.addEventListener('beforeunload', function() {{
4327
4328
  # 只统计用户可见的消息数(排除 llm_output 和 conversation_insight)
4328
4329
  if agent:
4329
4330
  # 将 agent 路径转为数字 ID,精确过滤
4330
- target_aid = self.core.memory.get_agent_id(agent) if agent else 0
4331
- # 统一使用 agent_id 精确匹配,不再兼容旧数据
4331
+ target_aid = self.core.memory.get_agent_id(agent)
4332
+ # 统一使用 agent_id 精确匹配
4332
4333
  rows = conn.execute(
4333
4334
  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
+ agent_id as raw_agent_id FROM memories
4335
4336
  WHERE category = 'session' AND role != ''
4336
4337
  AND key NOT IN {_hidden}
4337
4338
  AND agent_id = ?
4338
4339
  GROUP BY session_id ORDER BY last DESC LIMIT 100""",
4339
- (target_aid, target_aid)).fetchall()
4340
+ (target_aid,)).fetchall()
4340
4341
  else:
4341
4342
  # [v1.27.2] 无 agent 过滤时也返回 agent_id,供后台管理页面使用
4342
4343
  rows = conn.execute(
4343
4344
  f"SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last, "
4344
- f"MAX(CASE WHEN agent_id > 0 THEN agent_id ELSE NULL END) as raw_agent_id FROM memories "
4345
+ f"agent_id as raw_agent_id FROM memories "
4345
4346
  f"WHERE category = 'session' AND role != '' "
4346
4347
  f"AND key NOT IN {_hidden} "
4347
4348
  f"GROUP BY session_id ORDER BY last DESC LIMIT 100").fetchall()
@@ -4354,7 +4355,7 @@ window.addEventListener('beforeunload', function() {{
4354
4355
  agent_name = _agent_id_map.get(int(raw_aid), "")
4355
4356
  sessions.append({"id": r["session_id"], "messages": r["cnt"], "last": r["last"],
4356
4357
  "agent_id": agent_name, # 返回 agent 名称(非数字 ID)
4357
- "agent_db_id": (int(raw_aid) if raw_aid is not None else 0), # 数字 ID 供 URL 使用
4358
+ "agent_db_id": int(raw_aid), # 数字 ID 供 URL 使用
4358
4359
  "display_name": "", "preview": ""})
4359
4360
  # 批量获取自定义会话名称
4360
4361
  sids = [s["id"] for s in sessions]
@@ -6363,7 +6364,7 @@ window.addEventListener('beforeunload', function() {{
6363
6364
  recent = agent.memory.get_conversation(session_id, limit=3)
6364
6365
  _has_assistant = any(e.role == "assistant" for e in recent)
6365
6366
  if not _has_assistant and final_response and final_response.strip():
6366
- _fallback_agent_id = context.metadata.get("agent_db_id", 0)
6367
+ _fallback_agent_id = context.metadata.get("agent_db_id", 1)
6367
6368
  agent.memory.add_session(agent_id=_fallback_agent_id,
6368
6369
  session_id=session_id, role="assistant", content=final_response,
6369
6370
  )
@@ -405,12 +405,19 @@ async function deleteAgentKB(path,filename){
405
405
 
406
406
  async function loadAgentSessions(){
407
407
  const path=window._currentEditAgentPath;if(!path)return;
408
+ // 查找该 agent 的数字 ID(aid)
409
+ var _editAgentAid = 1;
410
+ if (typeof allAgentsCache !== 'undefined' && Array.isArray(allAgentsCache)) {
411
+ for (var i = 0; i < allAgentsCache.length; i++) {
412
+ if (allAgentsCache[i].path === path) { _editAgentAid = allAgentsCache[i].aid || 1; break; }
413
+ }
414
+ }
408
415
  const data=await api(`/api/agents/${encodeURIComponent(path)}/sessions`);
409
416
  const sessions=Array.isArray(data)?data:(data?.sessions||[]);
410
417
  let html=`<div class="flex justify-between items-center mb-16"><h4 style="font-size:14px;color:var(--text2)">会话 (${sessions.length})</h4></div>`;
411
418
  if(sessions.length===0){html+='<div class="empty">暂无会话</div>';}
412
419
  else{html+='<div class="table-wrap"><table><tr><th>会话</th><th>消息数</th><th>最后活动</th><th></th></tr>';
413
- for(const s of sessions){const dn=s.display_name||s.id;html+=`<tr><td style="max-width:200px;overflow:hidden;text-overflow:ellipsis" title="${escHtml(s.id)}">${escHtml(dn.length>25?dn.slice(0,25)+'...':dn)}</td><td>${s.messages||0}</td><td>${fmtTimeAgo(s.last)}</td><td><button class="btn btn-sm" style="background:var(--success);color:#fff" onclick="enterSession('${escHtml(s.id)}','${escHtml(path)}')">切入</button> <button class="btn btn-sm btn-ghost" onclick="viewSessionMsgs('${escHtml(s.id)}')">查看</button></td></tr>`}
420
+ for(const s of sessions){const dn=s.display_name||s.id;html+=`<tr><td style="max-width:200px;overflow:hidden;text-overflow:ellipsis" title="${escHtml(s.id)}">${escHtml(dn.length>25?dn.slice(0,25)+'...':dn)}</td><td>${s.messages||0}</td><td>${fmtTimeAgo(s.last)}</td><td><button class="btn btn-sm" style="background:var(--success);color:#fff" onclick="enterSession('${escHtml(s.id)}',${_editAgentAid})">切入</button> <button class="btn btn-sm btn-ghost" onclick="viewSessionMsgs('${escHtml(s.id)}')">查看</button></td></tr>`}
414
421
  html+='</table></div>';}
415
422
  $('sessionsContent').innerHTML=html;
416
423
  }
@@ -556,10 +563,18 @@ function confirmDeleteAgent(path,name){
556
563
  });
557
564
  }
558
565
 
559
- // 直接以执行模式打开与指定 Agent 的对话
560
- // [v1.27.2] 使用 a 参数(UrlCodec 编码),不再明文暴露 agent 路径
566
+ // 直接以执行模式打开与指定 Agent 的对话(使用 aid 数字 ID)
561
567
  function chatWithAgent(path){
562
- window.location.href='/ui/chat/chat_container.html?mode=exec&a='+UrlCodec.encode(path);
568
+ // 查找该 agent 的数字 ID
569
+ var _aid = null;
570
+ if (typeof allAgentsCache !== 'undefined' && Array.isArray(allAgentsCache)) {
571
+ for (var i = 0; i < allAgentsCache.length; i++) {
572
+ if (allAgentsCache[i].path === path) { _aid = allAgentsCache[i].aid; break; }
573
+ }
574
+ }
575
+ var url = '/ui/chat/chat_container.html?mode=exec';
576
+ if (_aid) url += '&aid=' + _aid;
577
+ window.location.href = url;
563
578
  }
564
579
 
565
580
  if (typeof window._adminRenderers === 'undefined') window._adminRenderers = {};
@@ -158,26 +158,26 @@ document.getElementById('adminSidebar')?.addEventListener('click',function(e){
158
158
  loadVersion();
159
159
  setTimeout(()=>checkUpdate(false),30000);
160
160
 
161
- // [v1.23.81] 返回聊天:通过纯数字 session ID 恢复群聊(不再传递 group_id)
161
+ // 返回聊天:通过 aid(数字 agent ID)和 session 参数恢复
162
162
  (function(){
163
163
  function _buildReturnUrl(){
164
164
  var params=new URLSearchParams(window.location.search);
165
165
  var base='/ui/chat/chat_container.html';
166
- // 从 URL 参数中恢复聊天状态
167
- var agent=params.get('from_agent');
166
+ // 从 URL 参数中恢复聊天状态(统一使用 aid 数字 ID)
167
+ var aid=params.get('from_aid');
168
168
  var session=params.get('from_session');
169
- // [v1.23.81] 群聊纯数字 session ID(优先级最高,覆盖 ?s= 个人会话参数)
170
- var groupSession=params.get('from_group_session');
169
+ // 群聊纯数字 session ID(优先级最高,覆盖 ?s= 个人会话参数)
170
+ var groupSession=params.get('from_g');
171
171
  var mode=params.get('from_mode');
172
172
  var parts=[];
173
173
  // 如果有群聊 session,用 ?g= 参数(纯数字 ID)
174
174
  if(groupSession && /^[0-9]+$/.test(groupSession)){
175
175
  parts.push('g='+groupSession);
176
- if(agent)parts.push('a='+encodeURIComponent(agent));
176
+ if(aid)parts.push('aid='+aid);
177
177
  if(mode)parts.push('mode='+encodeURIComponent(mode));
178
178
  } else {
179
179
  // 个人聊天模式
180
- if(agent)parts.push('a='+encodeURIComponent(agent));
180
+ if(aid)parts.push('aid='+aid);
181
181
  if(mode)parts.push('mode='+encodeURIComponent(mode));
182
182
  if(session)parts.push('s='+encodeURIComponent(session));
183
183
  }
@@ -11,18 +11,8 @@ async function renderSessions(){
11
11
  }
12
12
  let html='<div class="table-wrap"><table><tr><th>会话</th><th>Agent</th><th>消息数</th><th>最后活动</th><th>操作</th></tr>';
13
13
  for(const s of (ss||[])){
14
- // [v1.27.2] 优先使用后端返回的 agent_id(现在是 agent 名称),回退从前缀猜测
14
+ // 使用后端返回的 agent_idagent 名称)
15
15
  let agentName=s.agent_id||'';
16
- if(!agentName){
17
- // 回退:从 session_id 前缀提取(兼容旧格式)
18
- if((s.id||'').indexOf('_web_')>=0){
19
- agentName=(s.id||'').split('_web_')[0]||'default';
20
- }else if((s.id||'').indexOf('_cli_')>=0){
21
- agentName=(s.id||'').split('_cli_')[0]||'default';
22
- }else{
23
- agentName='default';
24
- }
25
- }
26
16
  const displayName=s.display_name||s.id;
27
17
  const dbId=s.agent_db_id||1;
28
18
  html+=`<tr><td title="${escHtml(s.id)}">${escHtml(displayName.length>30?displayName.slice(0,30)+'...':displayName)}</td><td>${escHtml(agentName)}</td><td>${s.messages}</td><td>${s.last?.slice(0,19)||''}</td>
@@ -86,19 +86,20 @@ function closeMobileAgentPanel() {
86
86
  if (overlay) overlay.classList.remove('active');
87
87
  }
88
88
 
89
- // [v1.23.81] 跳转后台管理:携带当前聊天上下文(agent、session、群聊session ID),以便"返回聊天"正确恢复
89
+ // 跳转后台管理:携带当前聊天上下文(aid数字ID、session、群聊ID),以便"返回聊天"正确恢复
90
90
  function goToAdmin() {
91
91
  var params = new URLSearchParams();
92
92
  var page = 'dashboard';
93
- // 传递当前聊天状态,供"返回聊天"恢复
94
- if (state.activeAgent) params.set('from_agent', state.activeAgent);
93
+ // 传递当前聊天状态,供"返回聊天"恢复(统一使用 aid 数字 ID)
94
+ var _curAgentObj = findAgentByPath(state.activeAgent);
95
+ if (_curAgentObj && _curAgentObj.aid) params.set('from_aid', _curAgentObj.aid);
95
96
  if (state.chatMode) params.set('from_mode', state.chatMode);
96
97
  if (state.activeSessionId && currentView !== 'group') params.set('from_session', state.activeSessionId);
97
- // [v1.23.81] 传递群聊纯数字 session ID(从 URL 读取),而非 JS 变量
98
+ // 传递群聊纯数字 session ID(从 URL 读取)
98
99
  if (typeof currentView !== 'undefined' && currentView === 'group') {
99
100
  var urlP = new URLSearchParams(window.location.search);
100
101
  var gSession = urlP.get('g');
101
- if (gSession) params.set('from_group_session', gSession);
102
+ if (gSession) params.set('from_g', gSession);
102
103
  }
103
104
  // 保留原始 ?page= 参数
104
105
  var origParams = new URLSearchParams(window.location.search);
@@ -356,10 +357,7 @@ const StatePersistence = {
356
357
  if (savedSessionId) {
357
358
  state._pendingSessionRestore = savedSessionId;
358
359
  }
359
- // [v1.23.81] 不再从 localStorage 恢复群聊状态(统一由 URL ?g= 参数恢复)
360
- // 仅保留兼容处理:如果旧版遗留了 localStorage 群聊状态,清除它
361
- StatePersistence.remove('currentView');
362
- StatePersistence.remove('currentGroupId');
360
+ // 群聊状态统一由 URL ?g= 参数恢复,不从 localStorage 恢复
363
361
  },
364
362
  /** 标记 setup 已完成(避免每次刷新弹出向导) */
365
363
  markSetupDone() { StatePersistence.save('setupDone', true); },
@@ -376,19 +374,13 @@ async function initChat() {
376
374
  initAttachmentUI();
377
375
 
378
376
  // URL 参数处理: ?aid=数字ID&mode=exec&s=编码session&g=群聊ID&popout=1
379
- // [v1.27.2] 使用 aid(数字 agent ID)代替明文 agent 名字
380
377
  const urlParams = new URLSearchParams(window.location.search);
381
378
  const urlAid = parseInt(urlParams.get('aid') || '', 10) || 0;
382
- // 兼容旧格式 ?a= 编码 或 ?agent= 明文
383
- const urlAgentLegacy = UrlCodec.decode(urlParams.get('a') || '') || UrlCodec.decode(urlParams.get('agent') || '');
384
379
  const urlMode = urlParams.get('mode');
385
- const urlSession = UrlCodec.decode(urlParams.get('s') || '') || UrlCodec.decode(urlParams.get('session') || '');
380
+ const urlSession = UrlCodec.decode(urlParams.get('s') || '');
386
381
  const isPopout = urlParams.get('popout') === '1';
387
- // [v1.23.81] 群聊纯数字 session ID(?g= 参数,优先级最高)
382
+ // 群聊纯数字 session ID(?g= 参数,优先级最高)
388
383
  const urlGroupSession = urlParams.get('g') || '';
389
- // 兼容旧版 ?group= 参数(从后台管理返回时的旧格式)
390
- const urlGroupSessionLegacy = urlParams.get('from_group_session') || '';
391
- const _effectiveGroupSession = urlGroupSession || urlGroupSessionLegacy;
392
384
  if (urlMode === 'chat' || urlMode === 'exec') {
393
385
  state.chatMode = urlMode;
394
386
  }
@@ -473,26 +465,11 @@ async function initChat() {
473
465
  state.agentsFlat.forEach(function(a) {
474
466
  if (a.aid) _aidToPath[a.aid] = a.path;
475
467
  });
476
- // 从 URL 解析 agent: 优先 aid(数字),兼容 a/agent(编码/明文)
468
+ // 从 URL 解析 agent: 仅支持 aid(数字 agent ID)
477
469
  var urlAgent = '';
478
470
  if (urlAid && _aidToPath[urlAid]) {
479
471
  urlAgent = _aidToPath[urlAid];
480
- } else if (urlAgentLegacy) {
481
- urlAgent = urlAgentLegacy;
482
472
  }
483
- // 清理 URL 中的旧格式参数(agent/a/session),统一使用 aid/s
484
- try {
485
- var _cleanUrl = new URL(window.location.href);
486
- _cleanUrl.searchParams.delete('agent');
487
- _cleanUrl.searchParams.delete('a');
488
- _cleanUrl.searchParams.delete('session');
489
- if (urlAgent && !urlAid) {
490
- // 如果没有 aid 但有旧格式 agent,添加 aid
491
- var _agentObj = findAgentByPath(urlAgent);
492
- if (_agentObj && _agentObj.aid) _cleanUrl.searchParams.set('aid', _agentObj.aid);
493
- }
494
- window.history.replaceState({}, '', _cleanUrl.toString());
495
- } catch (_) {}
496
473
 
497
474
  if (isPopout) {
498
475
  const agentObj = findAgentByPath(urlAgent);
@@ -520,12 +497,12 @@ async function initChat() {
520
497
  }
521
498
 
522
499
  // 如果 URL 中有 ?g= 纯数字 session ID,优先恢复群聊
523
- if (_effectiveGroupSession && /^[0-9]+$/.test(_effectiveGroupSession)) {
500
+ if (urlGroupSession && /^[0-9]+$/.test(urlGroupSession)) {
524
501
  if (urlAgent && urlAgent !== state.activeAgent) {
525
502
  state.activeAgent = urlAgent;
526
503
  StatePersistence.save('activeAgent', urlAgent);
527
504
  }
528
- _restoreGroupBySession(_effectiveGroupSession);
505
+ _restoreGroupBySession(urlGroupSession);
529
506
  } else if (urlAgent) {
530
507
  var resolved = urlAgent;
531
508
  if (!findAgentByPath(resolved)) {
@@ -2659,7 +2636,7 @@ async function loadSessions() {
2659
2636
  // 优先级: URL session 参数 > localStorage 持久化的 session > 最新 session
2660
2637
  // [fix] 所有候选 session ID 必须属于当前 agent 的会话列表,防止错乱到其它 agent 的历史对话
2661
2638
  const urlParams = new URLSearchParams(window.location.search);
2662
- const urlSession = UrlCodec.decode(urlParams.get('s') || '') || UrlCodec.decode(urlParams.get('session') || '');
2639
+ const urlSession = UrlCodec.decode(urlParams.get('s') || '');
2663
2640
  var targetSessionId = null;
2664
2641
 
2665
2642
  if (urlSession && state.sessions.some(s => s.id === urlSession)) {
@@ -2838,13 +2815,9 @@ function newChat() {
2838
2815
  state.activeSessionId = '__new__';
2839
2816
  state._selectedSessionLabel = null; // [v1.18.9] 清除选中的会话名称
2840
2817
  // ── 更新 URL(新对话移除 session 参数) ──
2841
- // [v1.27.2] 使用 aid 代替 a
2842
2818
  try {
2843
2819
  const url = new URL(window.location.href);
2844
2820
  url.searchParams.delete('s');
2845
- url.searchParams.delete('session');
2846
- url.searchParams.delete('a');
2847
- url.searchParams.delete('agent');
2848
2821
  var _ncAgentObj = findAgentByPath(state.activeAgent);
2849
2822
  if (_ncAgentObj && _ncAgentObj.aid) {
2850
2823
  url.searchParams.set('aid', _ncAgentObj.aid);
@@ -2998,10 +2971,6 @@ async function selectSession(id) {
2998
2971
  try {
2999
2972
  const url = new URL(window.location.href);
3000
2973
  url.searchParams.set('s', UrlCodec.encode(id));
3001
- // 移除旧格式参数
3002
- url.searchParams.delete('a');
3003
- url.searchParams.delete('agent');
3004
- url.searchParams.delete('session');
3005
2974
  // 设置 aid(数字 agent ID)
3006
2975
  var _selAgentObj = findAgentByPath(state.activeAgent);
3007
2976
  if (_selAgentObj && _selAgentObj.aid) {
@@ -1648,10 +1648,6 @@ async function sendMessage(opts) {
1648
1648
  try {
1649
1649
  const url = new URL(window.location.href);
1650
1650
  url.searchParams.set('s', UrlCodec.encode(sessionId));
1651
- // [v1.27.2] 使用 aid 代替 a
1652
- url.searchParams.delete('a');
1653
- url.searchParams.delete('agent');
1654
- url.searchParams.delete('session');
1655
1651
  var _feAgentObj = (typeof findAgentByPath === 'function') ? findAgentByPath(state.activeAgent) : null;
1656
1652
  if (_feAgentObj && _feAgentObj.aid) url.searchParams.set('aid', _feAgentObj.aid);
1657
1653
  window.history.replaceState({}, '', url.toString());
@@ -2502,7 +2498,7 @@ async function handleInjectChoice(choice) {
2502
2498
  clearDraft();
2503
2499
 
2504
2500
  try {
2505
- const rawSid = state.activeSessionId ? state.activeSessionId.replace(`${state.activeAgent}_`, '') : 'web_default';
2501
+ const rawSid = state.activeSessionId || 'web_default';
2506
2502
  const resp = await fetch('/api/chat/inject', {
2507
2503
  method: 'POST',
2508
2504
  headers: { 'Content-Type': 'application/json' },
@@ -2879,10 +2875,6 @@ const StreamingRecovery = {
2879
2875
  try {
2880
2876
  const url = new URL(window.location.href);
2881
2877
  url.searchParams.set('s', UrlCodec.encode(sessionId));
2882
- // [v1.27.2] 使用 aid 代替 a
2883
- url.searchParams.delete('a');
2884
- url.searchParams.delete('agent');
2885
- url.searchParams.delete('session');
2886
2878
  var _rvAgentObj = (typeof findAgentByPath === 'function') ? findAgentByPath(state.activeAgent) : null;
2887
2879
  if (_rvAgentObj && _rvAgentObj.aid) url.searchParams.set('aid', _rvAgentObj.aid);
2888
2880
  window.history.replaceState({}, '', url.toString());
@@ -255,8 +255,9 @@ async function selectGroup(gid) {
255
255
  var sessionId = sessionData.sid;
256
256
  // 用群聊专用 ?g= 参数更新 URL(不刷新页面),纯数字 session ID
257
257
  var newUrl = '/ui/chat/chat_container.html?g=' + sessionId;
258
- if (typeof state !== 'undefined' && state.activeAgent) {
259
- newUrl += '&a=' + encodeURIComponent(state.activeAgent);
258
+ var _grpAgentObj = (typeof findAgentByPath === 'function') ? findAgentByPath(state.activeAgent) : null;
259
+ if (_grpAgentObj && _grpAgentObj.aid) {
260
+ newUrl += '&aid=' + _grpAgentObj.aid;
260
261
  }
261
262
  window.history.replaceState({groupSession: sessionId, groupId: gid}, '', newUrl);
262
263
  }
@@ -344,13 +345,14 @@ function exitGroupChat() {
344
345
  currentView = 'chat';
345
346
  currentGroupId = null;
346
347
  groupMessages = [];
347
- // [v1.23.81] 清除群聊 ?g= session URL,恢复普通聊天 URL
348
+ // 清除群聊 ?g= session URL,恢复普通聊天 URL(统一使用 aid 数字 ID)
348
349
  var cleanUrl = '/ui/chat/chat_container.html';
349
- if (typeof state !== 'undefined' && state.activeAgent && state.activeAgent !== (typeof findMasterAgentPath === 'function' ? findMasterAgentPath() : '1')) {
350
- cleanUrl += '?a=' + encodeURIComponent(state.activeAgent);
350
+ var _exitAgentObj = (typeof findAgentByPath === 'function') ? findAgentByPath(state.activeAgent) : null;
351
+ if (_exitAgentObj && _exitAgentObj.aid) {
352
+ cleanUrl += '?aid=' + _exitAgentObj.aid;
351
353
  }
352
354
  if (typeof state !== 'undefined' && state.activeSessionId && state.activeSessionId !== '__new__') {
353
- cleanUrl += (cleanUrl.indexOf('?') >= 0 ? '&' : '?') + 's=' + encodeURIComponent(state.activeSessionId);
355
+ cleanUrl += (cleanUrl.indexOf('?') >= 0 ? '&' : '?') + 's=' + UrlCodec.encode(state.activeSessionId);
354
356
  }
355
357
  window.history.replaceState({}, '', cleanUrl);
356
358
  // 清除群聊 localStorage 持久化状态
@@ -456,8 +458,9 @@ function startPrivateChatFromGroup(agentPath) {
456
458
  StatePersistence.remove('currentGroupId');
457
459
  // 清除群聊 URL 中的 ?g= 参数
458
460
  var cleanUrl = '/ui/chat/chat_container.html';
459
- if (typeof state !== 'undefined' && agentPath && agentPath !== (typeof findMasterAgentPath === 'function' ? findMasterAgentPath() : '1')) {
460
- cleanUrl += '?a=' + encodeURIComponent(agentPath);
461
+ var _memAgentObj = (typeof findAgentByPath === 'function') ? findAgentByPath(agentPath) : null;
462
+ if (_memAgentObj && _memAgentObj.aid) {
463
+ cleanUrl += '?aid=' + _memAgentObj.aid;
461
464
  }
462
465
  window.history.replaceState({}, '', cleanUrl);
463
466
  // 让 selectAgent 处理完整的私聊切换