myagent-ai 1.15.49 → 1.15.51

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.
@@ -749,8 +749,8 @@ class UpdateManager:
749
749
  pkg_data = json.loads((PROJECT_ROOT / "package.json").read_text(encoding="utf-8"))
750
750
  pkg_name = pkg_data.get("name", "myagent-ai")
751
751
 
752
- # 构建 npm install 命令
753
- npm_cmd = ["npm", "install", "-g", pkg_name]
752
+ # 构建 npm install 命令 — 使用 @latest 确保拉取最新版本,避免缓存
753
+ npm_cmd = ["npm", "install", "-g", f"{pkg_name}@latest"]
754
754
  if registry != "https://registry.npmjs.org":
755
755
  npm_cmd.extend(["--registry", registry])
756
756
  logger.info(f"使用 npm 镜像: {registry}")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.15.49",
3
+ "version": "1.15.51",
4
4
  "description": "本地桌面端执行型AI助手 - Open Interpreter 风格 | Local Desktop Execution-Oriented AI Assistant",
5
5
  "main": "main.py",
6
6
  "bin": {
@@ -181,6 +181,7 @@ input,textarea,select{font:inherit}
181
181
  .sidebar-footer{
182
182
  padding:12px 16px;border-top:1px solid var(--border-light);
183
183
  display:flex;flex-direction:column;gap:6px;
184
+ flex-shrink:0;
184
185
  }
185
186
  .sidebar-footer-btn{
186
187
  display:flex;align-items:center;gap:10px;padding:8px 12px;
@@ -2098,7 +2099,7 @@ body.popout-mode #popoutBtn{display:none !important}
2098
2099
  .sidebar.collapsed .sidebar-search{flex-direction:column}
2099
2100
  .sidebar.collapsed .session-list{flex-direction:column}
2100
2101
  .sidebar.collapsed .sidebar-footer{flex-direction:column}
2101
- .sidebar-footer{padding-bottom:max(12px, env(safe-area-inset-bottom))}
2102
+ .sidebar-footer{padding-bottom:max(16px, calc(env(safe-area-inset-bottom) + 8px))}
2102
2103
 
2103
2104
  /* ── Header ── */
2104
2105
  .main-header{
package/web/ui/index.html CHANGED
@@ -38,7 +38,7 @@ body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;b
38
38
  .sidebar{width:220px;background:var(--surface);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0}
39
39
  .sidebar .logo{padding:20px;font-size:18px;font-weight:700;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px}
40
40
  .sidebar .logo span{color:var(--primary)}
41
- .nav{flex:1;padding:8px;overflow-y:auto}
41
+ .nav{flex:1;padding:8px;overflow-y:auto;min-height:0}
42
42
  .nav-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:var(--radius);cursor:pointer;color:var(--text2);font-size:14px;transition:all .15s;margin-bottom:2px}
43
43
  .nav-item:hover{background:var(--surface2);color:var(--text)}
44
44
  .nav-item.active{background:var(--primary);color:#fff}
@@ -180,6 +180,7 @@ tr:hover{background:var(--surface2)}
180
180
  .sidebar.mobile-open .logo .logo-text{display:inline!important}
181
181
  .sidebar.mobile-open.collapsed .nav-item{justify-content:flex-start;padding:8px 12px}
182
182
  .sidebar.mobile-open.collapsed .logo{justify-content:flex-start;padding:16px 12px}
183
+ .sidebar-footer-text{padding-bottom:max(12px, calc(env(safe-area-inset-bottom) + 8px))}
183
184
  .mobile-overlay{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:45;display:none}
184
185
  .mobile-overlay.active{display:block}
185
186
  .header{padding:12px 16px}
@@ -241,7 +242,7 @@ tr:hover{background:var(--surface2)}
241
242
  <div class="nav-item" data-tooltip="查看日志" onclick="showPage('logs')"><span class="icon">📋</span><span class="icon-text">查看日志</span></div>
242
243
  <div class="nav-item" data-tooltip="任务记录" onclick="showPage('tasks')"><span class="icon">📌</span><span class="icon-text">任务记录</span></div>
243
244
  </div>
244
- <div style="padding:12px;border-top:1px solid var(--border);font-size:12px;color:var(--text2)" class="sidebar-footer-text">
245
+ <div style="padding:12px;border-top:1px solid var(--border);font-size:12px;color:var(--text2);flex-shrink:0" class="sidebar-footer-text">
245
246
  <span id="sidebarVersion">v...</span>
246
247
  <span id="updateBadge" style="display:none;margin-left:6px;color:var(--danger);font-weight:bold;cursor:pointer" onclick="doUpdate()" title="点击更新">[有新版本]</span>
247
248
  · <a href="#" onclick="api('/api/status').then(r=>showToast('Running: '+r.running,'success'))" style="color:var(--primary)">状态</a>
@@ -353,7 +354,7 @@ function showConfirm(title,msg,onOk){
353
354
  <button class="btn btn-ghost" onclick="closeModal()">取消</button></div></div></div>`;
354
355
  }
355
356
 
356
- function showPage(page){
357
+ function showPage(page, addHistory){
357
358
  closeMobileSidebar();
358
359
  currentPage=page;
359
360
  document.querySelectorAll('.nav-item').forEach((n,i)=>n.classList.toggle('active',Object.keys(pages)[i]===page));
@@ -362,8 +363,69 @@ function showPage(page){
362
363
  if(renderers[page]){
363
364
  try{renderers[page]();}catch(e){console.error('Page render error:',e);$('content').innerHTML='<div class="empty" style="color:var(--danger)">页面加载失败: '+escHtml(e.message)+'</div>';}
364
365
  }
366
+ // 记录到浏览器历史
367
+ if(addHistory!==false){
368
+ var _sub=window._navSubState||null;
369
+ var hash=page+(_sub?'~'+_sub:'');
370
+ history.pushState({page:page,sub:_sub},'','#'+hash);
371
+ }
372
+ }
373
+
374
+ // 导航历史系统:记录子页面跳转(如 viewSession、viewSessionRaw)
375
+ // _navHistory: [{page,sub}] 最多6步
376
+ var _navHistory=[];
377
+ var _navSubState=null;
378
+
379
+ function navigateTo(page, sub, renderFn){
380
+ // 保存当前状态到历史
381
+ _navHistory.push({page:currentPage,sub:window._navSubState});
382
+ if(_navHistory.length>6)_navHistory.shift();
383
+ currentPage=page;
384
+ _navSubState=sub;
385
+ // 更新 URL hash
386
+ var hash=page+(sub?'~'+sub:'');
387
+ history.pushState({page:page,sub:sub},'','#'+hash);
388
+ // 更新导航高亮
389
+ document.querySelectorAll('.nav-item').forEach((n,i)=>n.classList.toggle('active',Object.keys(pages)[i]===page));
390
+ // 渲染页面
391
+ if(renderFn){
392
+ try{renderFn();}catch(e){console.error('Navigate render error:',e);}
393
+ }
365
394
  }
366
395
 
396
+ function goBack(){
397
+ if(_navHistory.length>0){
398
+ var prev=_navHistory.pop();
399
+ currentPage=prev.page;
400
+ _navSubState=prev.sub;
401
+ var hash=prev.page+(prev.sub?'~'+prev.sub:'');
402
+ history.pushState({page:prev.page,sub:prev.sub},'','#'+hash);
403
+ // 找到对应的渲染函数
404
+ var renderers={dashboard:renderDashboard,agents:renderAgents,platforms:renderPlatforms,organization:renderOrganization,departments:renderDepartments,sessions:renderSessions,memory:renderMemory,permissions:renderPermissions,llm:renderLLM,system:renderSystem,executor:renderExecutor,skills:renderSkills,files:renderFiles,logs:renderLogs,tasks:renderTasks};
405
+ if(renderers[prev.page]){
406
+ try{renderers[prev.page]();}catch(e){}
407
+ }
408
+ document.querySelectorAll('.nav-item').forEach((n,i)=>n.classList.toggle('active',Object.keys(pages)[i]===prev.page));
409
+ }else{
410
+ // 没有内部历史,尝试浏览器后退
411
+ history.back();
412
+ }
413
+ }
414
+
415
+ // 浏览器前进/后退按钮支持
416
+ window.addEventListener('popstate',function(e){
417
+ var s=e.state;
418
+ if(s&&s.page){
419
+ currentPage=s.page;
420
+ _navSubState=s.sub||null;
421
+ document.querySelectorAll('.nav-item').forEach((n,i)=>n.classList.toggle('active',Object.keys(pages)[i]===s.page));
422
+ var renderers={dashboard:renderDashboard,agents:renderAgents,platforms:renderPlatforms,organization:renderOrganization,departments:renderDepartments,sessions:renderSessions,memory:renderMemory,permissions:renderPermissions,llm:renderLLM,system:renderSystem,executor:renderExecutor,skills:renderSkills,files:renderFiles,logs:renderLogs,tasks:renderTasks};
423
+ if(renderers[s.page]){
424
+ try{renderers[s.page]();}catch(e){}
425
+ }
426
+ }
427
+ });
428
+
367
429
  // ========== Dashboard ==========
368
430
  async function renderDashboard(){
369
431
  const s=await api('/api/status');const m=await api('/api/memory/stats');
@@ -932,7 +994,8 @@ async function renderSessions(){
932
994
  }
933
995
  async function viewSession(sid){
934
996
  window._viewSessionSid=sid;window._viewSessionOffset=0;
935
- await _loadSessionMessages();
997
+ _navSubState='view:'+sid;
998
+ navigateTo('sessions','view:'+sid,_loadSessionMessages);
936
999
  }
937
1000
  async function _loadSessionMessages(){
938
1001
  const sid=window._viewSessionSid;if(!sid)return;
@@ -976,13 +1039,21 @@ async function _loadSessionMessages(){
976
1039
  }
977
1040
  html+='</div>';
978
1041
  if(hasMore)html+=`<button class="btn btn-ghost mt-8" onclick="window._viewSessionOffset=${offset+100};_loadSessionMessages()">加载更多...</button>`;
979
- html+='<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="renderSessions()">返回</button>';
1042
+ html+='<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="goBack()">返回</button>';
980
1043
  html+=`<button class="btn" style="background:var(--accent);color:#fff" onclick="viewSessionRaw('${escHtml(sid)}')">Raw 原始消息</button>`;
981
1044
  html+=`<button class="btn btn-primary" onclick="enterSession('${escHtml(sid)}','${escHtml(sid.split('_web_')[0]||'default')}')">在聊天中查看完整记录</button></div>`;
982
1045
  $('content').innerHTML=html;
983
1046
  }
984
1047
  // ========== Raw 原始消息查看 ==========
985
1048
  async function viewSessionRaw(sid){
1049
+ window._viewSessionSid=sid;
1050
+ _navSubState='raw:'+sid;
1051
+ // 不用 navigateTo 因为需要先 fetch 数据再渲染,直接记录历史后继续
1052
+ _navHistory.push({page:currentPage,sub:window._navSubState});
1053
+ if(_navHistory.length>6)_navHistory.shift();
1054
+ var hash='sessions'+'~raw:'+sid;
1055
+ history.pushState({page:'sessions',sub:'raw:'+sid},'','#'+hash);
1056
+
986
1057
  const msgs=await api(`/api/session/raw?sid=${encodeURIComponent(sid)}&limit=5000`);
987
1058
  if(!Array.isArray(msgs)){showToast('加载失败','danger');return}
988
1059
  // 按时间分组(同秒内合并)
@@ -1033,8 +1104,8 @@ async function viewSessionRaw(sid){
1033
1104
  html+=`</div></div>`;
1034
1105
  }
1035
1106
  html+=`</div>`;
1036
- html+=`<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="viewSession('${escHtml(sid)}')">返回查看</button>`;
1037
- html+=`<button class="btn btn-ghost" onclick="renderSessions()">返回会话列表</button></div>`;
1107
+ html+=`<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="goBack()">返回查看</button>`;
1108
+ html+=`<button class="btn btn-ghost" onclick="goBack()">返回会话列表</button></div>`;
1038
1109
  $('content').innerHTML=html;
1039
1110
  // 生成时间索引
1040
1111
  _buildTimeNav(msgs);
@@ -1140,7 +1211,7 @@ async function searchMemory(){
1140
1211
  }else{
1141
1212
  html+='<div class="empty">未找到匹配的记忆</div>';
1142
1213
  }
1143
- html+='<button class="btn btn-ghost mt-8" onclick="renderMemory()">返回</button>';$('content').innerHTML=html;
1214
+ html+='<button class="btn btn-ghost mt-8" onclick="goBack()">返回</button>';$('content').innerHTML=html;
1144
1215
  }
1145
1216
  async function deleteMemory(id){await api(`/api/memory/${id}`,{method:'DELETE'});renderMemory()}
1146
1217
  async function cleanupMemory(){const r=await api('/api/memory/cleanup',{method:'POST'});showToast('清理了 '+(r.cleaned||0)+' 条','success');renderMemory()}
@@ -2065,9 +2136,22 @@ async function sysLoadPreview(){
2065
2136
 
2066
2137
  // Init
2067
2138
  (function(){
2068
- var params=new URLSearchParams(window.location.search);
2069
- var page=params.get('page')||'dashboard';
2070
- if(pages[page])showPage(page);else showPage('dashboard');
2139
+ var hash=window.location.hash.slice(1)||'';
2140
+ var page=hash?hash.split('~')[0]:'';
2141
+ var sub=hash?hash.slice(page.length+1):'';
2142
+ // 兼容旧 URL query param ?page=xxx
2143
+ if(!page){
2144
+ var params=new URLSearchParams(window.location.search);
2145
+ page=params.get('page')||'dashboard';
2146
+ }
2147
+ if(sub)_navSubState=sub;
2148
+ if(pages[page]){
2149
+ history.replaceState({page:page,sub:sub||null},'','#'+page+(sub?'~'+sub:''));
2150
+ showPage(page,false);
2151
+ }else{
2152
+ history.replaceState({page:'dashboard',sub:null},'','#dashboard');
2153
+ showPage('dashboard',false);
2154
+ }
2071
2155
  })();
2072
2156
  setInterval(()=>{api('/api/status').catch(()=>{})},30000);
2073
2157