myagent-ai 1.23.22 → 1.23.24

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
@@ -318,12 +318,18 @@ class MemoryManager:
318
318
  return entries
319
319
 
320
320
  def get_conversation_all(self, session_id, limit=5000) -> List[MemoryEntry]:
321
- """获取全量对话历史(包含所有内部条目),用于完整回溯。"""
321
+ """获取全量对话历史(包含所有内部条目),用于完整回溯。limit=0 表示无限制。"""
322
322
  conn = self._get_conn()
323
- sql = """SELECT * FROM memories
324
- WHERE session_id = ? AND category = 'session' AND role != ''
325
- ORDER BY created_at ASC, rowid ASC LIMIT ?"""
326
- rows = conn.execute(sql, (session_id, limit)).fetchall()
323
+ if limit and limit > 0:
324
+ sql = """SELECT * FROM memories
325
+ WHERE session_id = ? AND category = 'session' AND role != ''
326
+ ORDER BY created_at ASC, rowid ASC LIMIT ?"""
327
+ rows = conn.execute(sql, (session_id, limit)).fetchall()
328
+ else:
329
+ sql = """SELECT * FROM memories
330
+ WHERE session_id = ? AND category = 'session' AND role != ''
331
+ ORDER BY created_at ASC, rowid ASC"""
332
+ rows = conn.execute(sql, (session_id,)).fetchall()
327
333
  return [MemoryEntry.from_row(row) for row in rows]
328
334
 
329
335
  def search_by_time_range(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myagent-ai",
3
- "version": "1.23.22",
3
+ "version": "1.23.24",
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
@@ -4269,9 +4269,9 @@ window.addEventListener('beforeunload', function() {{
4269
4269
  sid = request.match_info["sid"]
4270
4270
  if not self.core.memory:
4271
4271
  return web.json_response([])
4272
- limit = min(int(request.query.get("limit", 5000)), 5000)
4272
+ limit = int(request.query.get("limit", 0))
4273
4273
  offset = int(request.query.get("offset", 0))
4274
- entries = self.core.memory.get_conversation_all(sid, limit=limit + offset)
4274
+ entries = self.core.memory.get_conversation_all(sid, limit=limit + offset if limit else 0)
4275
4275
  entries = entries[offset:]
4276
4276
  return web.json_response([{
4277
4277
  "role": e.role, "content": e.content, "time": e.created_at,
@@ -4285,9 +4285,9 @@ window.addEventListener('beforeunload', function() {{
4285
4285
  return web.json_response([])
4286
4286
  if not self.core.memory:
4287
4287
  return web.json_response([])
4288
- limit = min(int(request.query.get("limit", 5000)), 5000)
4288
+ limit = int(request.query.get("limit", 0))
4289
4289
  offset = int(request.query.get("offset", 0))
4290
- entries = self.core.memory.get_conversation_all(sid, limit=limit + offset)
4290
+ entries = self.core.memory.get_conversation_all(sid, limit=limit + offset if limit else 0)
4291
4291
  entries = entries[offset:]
4292
4292
  return web.json_response([{
4293
4293
  "role": e.role, "content": e.content, "time": e.created_at,
@@ -192,24 +192,28 @@ window.addEventListener('popstate',function(e){
192
192
  let _deptTreeNeedsRefresh=false;
193
193
  function closeModal(){$('modalContainer').innerHTML='';if(_deptTreeNeedsRefresh){_deptTreeNeedsRefresh=false;renderDepartments()}}
194
194
 
195
- // Init
195
+ // Init — [v1.23.22] 使用 DOMContentLoaded 推迟到所有 admin 脚本加载后再执行
196
+ // 原因:此文件最先加载,此时 window._adminRenderers 尚未注册任何渲染器,
197
+ // showPage() 检查 renderers[page] 为空会静默跳过,导致内容区空白。
196
198
  (function(){
197
- var hash=window.location.hash.slice(1)||'';
198
- var page=hash?hash.split('~')[0]:'';
199
- var sub=hash?hash.slice(page.length+1):'';
200
- // 兼容旧 URL query param ?page=xxx
201
- if(!page){
202
- var params=new URLSearchParams(window.location.search);
203
- page=params.get('page')||'dashboard';
204
- }
205
- if(sub)_navSubState=sub;
206
- if(pages[page]){
207
- history.replaceState({page:page,sub:sub||null},'','#'+page+(sub?'~'+sub:''));
208
- showPage(page,false);
209
- }else{
210
- history.replaceState({page:'dashboard',sub:null},'','#dashboard');
211
- showPage('dashboard',false);
212
- }
199
+ window.addEventListener('DOMContentLoaded', function() {
200
+ var hash=window.location.hash.slice(1)||'';
201
+ var page=hash?hash.split('~')[0]:'';
202
+ var sub=hash?hash.slice(page.length+1):'';
203
+ // 兼容旧 URL query param ?page=xxx
204
+ if(!page){
205
+ var params=new URLSearchParams(window.location.search);
206
+ page=params.get('page')||'dashboard';
207
+ }
208
+ if(sub)_navSubState=sub;
209
+ if(pages[page]){
210
+ history.replaceState({page:page,sub:sub||null},'','#'+page+(sub?'~'+sub:''));
211
+ showPage(page,false);
212
+ }else{
213
+ history.replaceState({page:'dashboard',sub:null},'','#dashboard');
214
+ showPage('dashboard',false);
215
+ }
216
+ });
213
217
  })();
214
218
  setInterval(()=>{api('/api/status').catch(()=>{})},30000);
215
219
 
@@ -67,24 +67,28 @@ async function _loadSessionMessages(){
67
67
  $('content').innerHTML=html;
68
68
  }
69
69
  // ========== Raw 原始消息查看 ==========
70
+ // [v1.23.23] 缓存全量消息供最大化使用
71
+ var _rawMsgsCache=[];
70
72
  async function viewSessionRaw(sid){
71
73
  window._viewSessionSid=sid;
72
74
  _navSubState='raw:'+sid;
73
- // 不用 navigateTo 因为需要先 fetch 数据再渲染,直接记录历史后继续
74
75
  _navHistory.push({page:currentPage,sub:window._navSubState});
75
76
  if(_navHistory.length>6)_navHistory.shift();
76
77
  var hash='sessions'+'~raw:'+sid;
77
78
  history.pushState({page:'sessions',sub:'raw:'+sid},'','#'+hash);
78
79
 
79
- const msgs=await api(`/api/session/raw?sid=${encodeURIComponent(sid)}&limit=5000`);
80
+ const msgs=await api(`/api/session/raw?sid=${encodeURIComponent(sid)}`);
80
81
  if(!Array.isArray(msgs)){showToast('加载失败','danger');return}
81
- // 按时间分组(同秒内合并)
82
+ _rawMsgsCache=msgs;
83
+ _renderRawView(msgs,sid);
84
+ }
85
+
86
+ function _renderRawView(msgs,sid){
82
87
  const keyLabelMap={'llm_output':'LLM 输出','llm_input':'LLM 输入','tool_call':'工具调用','tool_result':'工具结果','tool_result_raw':'工具原始数据','reasoning':'推理过程','conversation_insight':'会话洞察','':'对话','llm_request':'LLM 请求'};
83
88
  let html=`<h3 style="margin-bottom:12px">Raw: ${escHtml(sid)} <span class="badge badge-blue">${msgs.length} 条</span></h3>`;
84
89
  // 筛选按钮
85
90
  html+=`<div style="margin-bottom:10px;display:flex;gap:6px;flex-wrap:wrap" id="rawFilterBar">`;
86
91
  html+=`<button class="btn btn-sm" style="background:var(--accent);color:#fff" data-filter="all" onclick="rawFilter('all',this)">全部</button>`;
87
- // 收集所有 key 类型
88
92
  const keys=[...new Set(msgs.map(m=>m.key||''))];
89
93
  for(const k of keys){
90
94
  const label=keyLabelMap[k]||k||'对话';
@@ -120,20 +124,57 @@ async function viewSessionRaw(sid){
120
124
  html+=`<span><span style="color:var(--text);font-weight:600">${escHtml(role)}</span>`;
121
125
  if(keyLabel)html+=` <span class="badge badge-blue" style="font-size:10px">${escHtml(keyLabel)}</span>`;
122
126
  html+=`</span>`;
123
- html+=`<span>${escHtml(time)} <span style="margin-left:4px;opacity:0.5">${content.length}字符</span></span>`;
127
+ html+=`<span>${escHtml(time)} <span style="margin-left:4px;opacity:0.5">${content.length}字符</span>`;
128
+ html+=` <span style="margin-left:8px;opacity:0.4;cursor:pointer" onclick="event.stopPropagation();rawMaximize(${i})" title="最大化查看">&#x2921;</span>`;
129
+ html+=`</span>`;
124
130
  html+=`</div>`;
125
131
  html+=`<div id="${mid}" class="raw-body" style="padding:4px 10px 8px;font-size:12px;white-space:pre-wrap;word-break:break-all;color:var(--text2);max-height:400px;overflow-y:auto;transition:max-height 0.2s">`;
126
- html+=escHtml(content.length>8000?content.slice(0,8000)+'\n... (共'+content.length+'字符)':content);
127
- if(content.length>8000)html+=`<button class="btn btn-sm btn-ghost" style="margin-top:4px;font-size:10px" onclick="event.stopPropagation();this.parentElement.textContent=this.dataset.full;this.remove()" data-full="${escHtml(content).replace(/"/g,'&quot;')}">展开全部 (${content.length}字符)</button>`;
132
+ // [v1.23.23] 不截断,全量显示
133
+ html+=escHtml(content);
128
134
  html+=`</div></div>`;
129
135
  }
130
136
  html+=`</div>`;
131
137
  html+=`<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="goBack()">返回查看</button>`;
132
138
  html+=`<button class="btn btn-ghost" onclick="goBack()">返回会话列表</button></div>`;
133
139
  $('content').innerHTML=html;
134
- // 生成时间索引
135
140
  _buildTimeNav(msgs);
136
141
  }
142
+
143
+ // [v1.23.23] 最大化查看单条 raw 消息(全屏覆盖,ESC 关闭)
144
+ function rawMaximize(idx){
145
+ if(!_rawMsgsCache||!_rawMsgsCache[idx])return;
146
+ const m=_rawMsgsCache[idx];
147
+ const content=m.content||'';
148
+ const role=m.role||'?';
149
+ const key=m.key||'';
150
+ const time=(m.time||'').slice(0,19);
151
+ const keyLabelMap={'llm_output':'LLM 输出','llm_input':'LLM 输入','tool_call':'工具调用','tool_result':'工具结果','tool_result_raw':'工具原始数据','reasoning':'推理过程','conversation_insight':'会话洞察','':'对话','llm_request':'LLM 请求'};
152
+ const keyLabel=keyLabelMap[key]||key||'对话';
153
+ const overlay=document.createElement('div');
154
+ overlay.id='rawMaxOverlay';
155
+ overlay.style.cssText='position:fixed;inset:0;z-index:300;background:rgba(0,0,0,.75);display:flex;flex-direction:column;padding:12px';
156
+ overlay.innerHTML=`<div style="display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background:var(--surface);border:1px solid var(--border);border-radius:8px 8px 0 0;flex-shrink:0">
157
+ <div><span style="font-weight:700;color:var(--text)">${escHtml(role)}</span> <span class="badge badge-blue" style="font-size:10px">${escHtml(keyLabel)}</span> <span style="font-size:12px;color:var(--text3);margin-left:8px">${escHtml(time)}</span> <span style="font-size:11px;color:var(--text3);margin-left:4px">${content.length} 字符</span></div>
158
+ <div style="display:flex;gap:8px">
159
+ <button class="btn btn-sm btn-ghost" onclick="rawMaxCopy(${idx})">复制</button>
160
+ <button class="btn btn-sm btn-ghost" onclick="rawMaxClose()">关闭 (ESC)</button>
161
+ </div>
162
+ </div>
163
+ <pre id="rawMaxContent" style="flex:1;overflow:auto;background:var(--bg);border:1px solid var(--border);border-top:none;border-radius:0 0 8px 8px;padding:16px;font-size:13px;line-height:1.6;white-space:pre-wrap;word-break:break-all;color:var(--text);margin:0;font-family:'Cascadia Code',Consolas,monospace">${escHtml(content)}</pre>`;
164
+ document.body.appendChild(overlay);
165
+ overlay.addEventListener('keydown',function(e){if(e.key==='Escape')rawMaxClose()});
166
+ overlay.focus();
167
+ }
168
+ // 全局 ESC 监听(overlay 可能没获得焦点)
169
+ document.addEventListener('keydown',function(e){if(e.key==='Escape'&&document.getElementById('rawMaxOverlay'))rawMaxClose()});
170
+ function rawMaxClose(){
171
+ var el=document.getElementById('rawMaxOverlay');
172
+ if(el)el.remove();
173
+ }
174
+ function rawMaxCopy(idx){
175
+ if(!_rawMsgsCache||!_rawMsgsCache[idx])return;
176
+ navigator.clipboard.writeText(_rawMsgsCache[idx].content||'').then(()=>showToast('已复制','success')).catch(()=>showToast('复制失败','danger'));
177
+ }
137
178
  function rawFilter(key,btn){
138
179
  const items=document.querySelectorAll('.raw-item');
139
180
  for(const item of items){