myagent-ai 1.18.9 → 1.19.0

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.
@@ -1589,13 +1589,17 @@ class MainAgent(BaseAgent):
1589
1589
  _fresult = await _fskill.execute(_fpath, _fdesc, stream_callback=stream_callback)
1590
1590
  result = {"success": True, "output": json.dumps(_fresult, ensure_ascii=False, indent=2), "data": _fresult}
1591
1591
  # [v1.18.5] 追踪发送的文件,用于持久化到会话记忆
1592
- if _fresult.get("success") and _fresult.get("file_id"):
1593
- _sent_files.append({
1594
- "id": _fresult["file_id"],
1595
- "name": _fresult.get("name", ""),
1596
- "type": _fresult.get("type", ""),
1597
- "size": _fresult.get("size", 0),
1598
- })
1592
+ # [v1.18.9] 修复:_sent_files 可能不在作用域内,安全处理
1593
+ try:
1594
+ if _fresult.get("success") and _fresult.get("file_id"):
1595
+ _sent_files.append({
1596
+ "id": _fresult["file_id"],
1597
+ "name": _fresult.get("name", ""),
1598
+ "type": _fresult.get("type", ""),
1599
+ "size": _fresult.get("size", 0),
1600
+ })
1601
+ except NameError:
1602
+ pass # _sent_files 不在当前作用域,跳过文件追踪
1599
1603
  except Exception as _fse:
1600
1604
  result = {"success": False, "error": f"文件发送失败: {_fse}"}
1601
1605
  logger.warning(f"[{task_id}] file_send 工具异常: {_fse}")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.18.9",
3
+ "version": "1.19.0",
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
@@ -4422,10 +4422,9 @@ window.toggleFullscreen = function() {{
4422
4422
  # 确保不会残留上次请求的知识库路径
4423
4423
  if agent_path and self.core.main_agent and self.core.main_agent.context_builder:
4424
4424
  agent_kb_dir = self._get_agent_knowledge_dir(agent_path)
4425
- if agent_kb_dir.exists() and any(agent_kb_dir.iterdir()):
4426
- self.core.main_agent.context_builder.agent_knowledge_dir = str(agent_kb_dir)
4427
- else:
4428
- self.core.main_agent.context_builder.agent_knowledge_dir = None
4425
+ # [v1.18.9] 始终设置 agent_knowledge_dir(即使目录为空),确保写入 Agent 专属目录
4426
+ agent_kb_dir.mkdir(parents=True, exist_ok=True)
4427
+ self.core.main_agent.context_builder.agent_knowledge_dir = str(agent_kb_dir)
4429
4428
 
4430
4429
  try:
4431
4430
  response = await self.core.process_message(message, session_id)
@@ -4723,11 +4722,10 @@ window.toggleFullscreen = function() {{
4723
4722
  # ── 设置 Agent 专属知识库目录(优先于组织知识库)──
4724
4723
  if agent_path and agent.context_builder:
4725
4724
  agent_kb_dir = self._get_agent_knowledge_dir(agent_path)
4726
- if agent_kb_dir.exists() and any(agent_kb_dir.iterdir()):
4727
- agent.context_builder.agent_knowledge_dir = str(agent_kb_dir)
4728
- logger.debug(f"[{session_id}] 使用 Agent 专属知识库: {agent_kb_dir}")
4729
- else:
4730
- agent.context_builder.agent_knowledge_dir = None
4725
+ # [v1.18.9] 始终设置 agent_knowledge_dir(即使目录为空),确保写入 Agent 专属目录
4726
+ agent_kb_dir.mkdir(parents=True, exist_ok=True)
4727
+ agent.context_builder.agent_knowledge_dir = str(agent_kb_dir)
4728
+ logger.debug(f"[{session_id}] 使用 Agent 专属知识库: {agent_kb_dir}")
4731
4729
 
4732
4730
  # Clear execution events from previous runs
4733
4731
  agent.clear_execution_events()
package/web/ui/index.html CHANGED
@@ -178,22 +178,35 @@ tr:hover{background:var(--surface2)}
178
178
  /* ── Mobile Responsive ── */
179
179
  @media(max-width:768px){
180
180
  body{flex-direction:column}
181
- .sidebar{position:fixed;left:0;top:0;height:100vh;width:260px;max-width:80vw;z-index:50;transform:translateX(-100%);transition:transform .3s ease;flex-shrink:0}
182
- .sidebar.mobile-open{transform:translateX(0)}
183
- .sidebar.collapsed{width:260px;transform:translateX(-100%)}
184
- .sidebar.collapsed.mobile-open{transform:translateX(0)}
185
- .sidebar-toggle{display:none!important}
186
- /* 移动端:即使桌面端折叠了侧边栏,打开时也要显示底部版本信息 */
187
- .sidebar.collapsed.mobile-open .sidebar-footer-text{display:block!important}
188
- /* 移动端:打开侧边栏时,即使桌面端折叠了,也要显示图标文字 */
181
+ /* [v1.18.9] 移动端侧边栏:默认显示为56px图标窄栏,展开为完整侧边栏 */
182
+ .sidebar{position:fixed;left:0;top:0;height:100vh;width:56px;z-index:50;transform:translateX(0);transition:width .3s ease,transform .3s ease;flex-shrink:0}
183
+ .sidebar .nav-item{justify-content:center;padding:10px 0;position:relative}
184
+ .sidebar .nav-item .icon-text{display:none}
185
+ .sidebar .logo .logo-text{display:none}
186
+ .sidebar .logo{justify-content:center;padding:20px 8px}
187
+ .sidebar .sidebar-footer-text{display:none}
188
+ /* 收起时显示 tooltip */
189
+ .sidebar .nav-item::after{
190
+ content:attr(data-tooltip);position:absolute;left:calc(100% + 8px);top:50%;transform:translateY(-50%);
191
+ padding:5px 10px;border-radius:6px;background:var(--text);color:var(--bg);font-size:12px;font-weight:500;
192
+ white-space:nowrap;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .15s,visibility .15s;z-index:100;box-shadow:0 2px 8px rgba(0,0,0,.15);
193
+ }
194
+ .sidebar .nav-item:hover::after{opacity:1;visibility:visible}
195
+ /* 展开状态:完整侧边栏 + 遮罩 */
196
+ .sidebar.mobile-open{width:260px;max-width:80vw}
197
+ .sidebar.mobile-open .nav-item{justify-content:flex-start;padding:8px 12px}
189
198
  .sidebar.mobile-open .nav-item .icon-text{display:inline!important}
199
+ .sidebar.mobile-open .nav-item::after{display:none}
190
200
  .sidebar.mobile-open .logo .logo-text{display:inline!important}
191
- .sidebar.mobile-open.collapsed .nav-item{justify-content:flex-start;padding:8px 12px}
192
- .sidebar.mobile-open.collapsed .logo{justify-content:flex-start;padding:16px 12px}
201
+ .sidebar.mobile-open .logo{justify-content:flex-start;padding:16px 12px}
202
+ .sidebar.mobile-open .sidebar-footer-text{display:block!important}
203
+ .sidebar.collapsed{width:56px;transform:translateX(0)}
204
+ .sidebar.collapsed.mobile-open{width:260px;max-width:80vw;transform:translateX(0)}
205
+ .sidebar-toggle{display:none!important}
193
206
  .sidebar-footer-text{padding-bottom:max(12px, calc(env(safe-area-inset-bottom) + 8px))}
194
207
  .mobile-overlay{position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:45;display:none}
195
208
  .mobile-overlay.active{display:block}
196
- .header{padding:12px 16px}
209
+ .header{padding:12px 16px;padding-left:68px}
197
210
  .header h2{font-size:16px}
198
211
  .content{padding:16px}
199
212
  .grid{grid-template-columns:1fr}
@@ -215,6 +228,12 @@ tr:hover{background:var(--surface2)}
215
228
  .toast{left:16px;right:16px;bottom:16px}
216
229
  .agent-card{flex-direction:column;align-items:flex-start}
217
230
  .agent-card .flex.flex-col{flex-direction:row;gap:4px}
231
+ /* [v1.18.9] 技能行移动端允许换行 */
232
+ .skill-row{flex-wrap:wrap}
233
+ .skill-row .flex{flex-wrap:wrap;gap:4px}
234
+ /* [v1.18.9] 任务表格优化 */
235
+ .table-wrap table{min-width:auto}
236
+ .table-wrap td[style*="max-width:300px"]{max-width:150px!important;white-space:normal!important;word-break:break-all}
218
237
  }
219
238
  @media(max-width:480px){
220
239
  .content{padding:12px}
@@ -1228,13 +1247,21 @@ function enterSession(sid,agentName){
1228
1247
 
1229
1248
  // ========== Memory ==========
1230
1249
  let _memCategory='global';
1250
+ let _memAgentFilter=''; // [v1.18.9] agent筛选
1231
1251
  async function renderMemory(){
1252
+ // [v1.18.9] 加载 agent 列表供筛选
1253
+ let agentOpts='<option value="">全部 Agent</option>';
1254
+ try{const ags=await api('/api/agents');
1255
+ if(ags&&ags.length){for(const a of ags){agentOpts+=`<option value="${escHtml(a.path||a.name)}" ${_memAgentFilter===(a.path||a.name)?'selected':''}>${escHtml(a.name||a.path)}</option>`;}
1256
+ }}catch(e){}
1232
1257
  let stats={},lt=[];
1233
1258
  try{stats=await api('/api/memory/stats')}catch(e){stats={error:e.message}}
1234
1259
  try{lt=await api('/api/memory/list?category='+encodeURIComponent(_memCategory))}catch(e){lt=[]}
1235
1260
  if(stats.error){$('content').innerHTML='<div class="empty" style="color:var(--danger)">记忆系统异常: '+escHtml(stats.error)+'</div>';return}
1261
+ // [v1.18.9] 按 agent 筛选
1262
+ if(_memAgentFilter){lt=lt.filter(e=>(e.agent_id||e.session_id||'').includes(_memAgentFilter));}
1236
1263
  const cats=[{k:'global',l:'全局记忆'},{k:'session',l:'会话记忆'}];
1237
- let tabHtml='<div class="flex gap-8 mb-8">';
1264
+ let tabHtml='<div class="flex gap-8 mb-8" style="flex-wrap:wrap">';
1238
1265
  for(const c of cats){
1239
1266
  const active=c.k===_memCategory?'btn-primary':'btn-ghost';
1240
1267
  const count=stats[c.k+'_count']||0;
@@ -1246,7 +1273,7 @@ async function renderMemory(){
1246
1273
  <div class="stat"><div class="label">全局记忆</div><div class="value">${stats.global_count||0}</div></div>
1247
1274
  <div class="stat"><div class="label">会话记忆</div><div class="value">${stats.session_count||0}</div></div></div>`;
1248
1275
  html+=tabHtml;
1249
- html+='<div class="flex gap-8 mb-16"><input id="memSearch" placeholder="搜索记忆..." onkeydown="if(event.key===\'Enter\')searchMemory()" style="max-width:400px"><button class="btn btn-primary" onclick="searchMemory()">搜索</button><button class="btn btn-ghost" onclick="cleanupMemory()">清理过期</button></div>';
1276
+ html+='<div class="flex gap-8 mb-16" style="flex-wrap:wrap"><select id="memAgentFilter" onchange="_memAgentFilter=this.value;renderMemory()" style="width:auto;min-width:140px">'+agentOpts+'</select><input id="memSearch" placeholder="搜索记忆..." onkeydown="if(event.key===\'Enter\')searchMemory()" style="max-width:300px"><button class="btn btn-primary" onclick="searchMemory()">搜索</button><button class="btn btn-ghost" onclick="cleanupMemory()">清理过期</button></div>';
1250
1277
  if(lt&&lt.length){
1251
1278
  const isSession=_memCategory==='session';
1252
1279
  html+='<div class="mem-list">';