myagent-ai 1.15.50 → 1.15.52
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 +26 -0
- package/memory/manager.py +1 -1
- package/package.json +1 -1
- package/web/api_server.py +3 -3
- package/web/ui/index.html +96 -11
package/agents/main_agent.py
CHANGED
|
@@ -6,6 +6,7 @@ agents/main_agent.py - 主 Agent
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
9
|
+
import json
|
|
9
10
|
import re
|
|
10
11
|
from typing import Any, Callable, Dict, List, Optional
|
|
11
12
|
|
|
@@ -576,6 +577,21 @@ class MainAgent(BaseAgent):
|
|
|
576
577
|
content=context.user_message or "请处理上述上下文。"
|
|
577
578
|
))
|
|
578
579
|
|
|
580
|
+
# [v1.15.52] 保存完整的 LLM 输入消息(system prompt + user message + 工具结果回调)
|
|
581
|
+
# 用于 Raw 查看器完整回溯 LLM 交互过程
|
|
582
|
+
if self.memory:
|
|
583
|
+
_input_parts = []
|
|
584
|
+
for _msg in messages:
|
|
585
|
+
_input_parts.append(f"=== {_msg.role.upper()} ===\n{_msg.content}")
|
|
586
|
+
_llm_input_text = "\n\n".join(_input_parts)
|
|
587
|
+
self.memory.add_session(
|
|
588
|
+
session_id=context.session_id,
|
|
589
|
+
role="system",
|
|
590
|
+
content=_llm_input_text,
|
|
591
|
+
key="llm_input",
|
|
592
|
+
importance=0.3,
|
|
593
|
+
)
|
|
594
|
+
|
|
579
595
|
if stream_response and self.llm:
|
|
580
596
|
response = await self._call_llm_stream(
|
|
581
597
|
messages, text_delta_callback=text_delta_callback,
|
|
@@ -1193,6 +1209,8 @@ class MainAgent(BaseAgent):
|
|
|
1193
1209
|
key="tool_call",
|
|
1194
1210
|
importance=0.4,
|
|
1195
1211
|
)
|
|
1212
|
+
# [v1.15.52] 保存完整的工具执行原始结果(不截断,原汁原味)
|
|
1213
|
+
_raw_result_str = json.dumps(tool_result, ensure_ascii=False, indent=2) if tool_result else str(tool_result)
|
|
1196
1214
|
self.memory.add_session(
|
|
1197
1215
|
session_id=context.session_id,
|
|
1198
1216
|
role="tool",
|
|
@@ -1200,6 +1218,14 @@ class MainAgent(BaseAgent):
|
|
|
1200
1218
|
key="tool_result",
|
|
1201
1219
|
importance=0.4,
|
|
1202
1220
|
)
|
|
1221
|
+
# 额外保存原始完整 JSON(用于 Raw 查看器完整回溯)
|
|
1222
|
+
self.memory.add_session(
|
|
1223
|
+
session_id=context.session_id,
|
|
1224
|
+
role="tool",
|
|
1225
|
+
content=f"[{tool_name}] 原始结果 ({_status})\n{truncate_str(_raw_result_str, 45000)}",
|
|
1226
|
+
key="tool_result_raw",
|
|
1227
|
+
importance=0.2,
|
|
1228
|
+
)
|
|
1203
1229
|
|
|
1204
1230
|
# 任一工具超时 → 立即停止执行剩余工具
|
|
1205
1231
|
if _has_timeout:
|
package/memory/manager.py
CHANGED
|
@@ -299,7 +299,7 @@ class MemoryManager:
|
|
|
299
299
|
# 只排除纯内部审计条目,保留 tool_call/tool_result 供前端展示
|
|
300
300
|
sql = """SELECT * FROM memories
|
|
301
301
|
WHERE session_id = ? AND category = 'session' AND role != ''
|
|
302
|
-
AND key NOT IN ('llm_output', 'conversation_insight')
|
|
302
|
+
AND key NOT IN ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight')
|
|
303
303
|
ORDER BY created_at ASC LIMIT ?"""
|
|
304
304
|
rows = conn.execute(sql, (session_id, limit)).fetchall()
|
|
305
305
|
entries = [MemoryEntry.from_row(row) for row in rows]
|
package/package.json
CHANGED
package/web/api_server.py
CHANGED
|
@@ -2499,14 +2499,14 @@ class ApiServer:
|
|
|
2499
2499
|
rows = self.core.memory._get_conn().execute(
|
|
2500
2500
|
"SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
|
|
2501
2501
|
"WHERE category = 'session' AND role != '' "
|
|
2502
|
-
"AND key NOT IN ('llm_output', 'conversation_insight') "
|
|
2502
|
+
"AND key NOT IN ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight') "
|
|
2503
2503
|
"AND session_id LIKE ? GROUP BY session_id ORDER BY last DESC LIMIT 100",
|
|
2504
2504
|
(prefix + "%",)).fetchall()
|
|
2505
2505
|
else:
|
|
2506
2506
|
rows = self.core.memory._get_conn().execute(
|
|
2507
2507
|
"SELECT DISTINCT session_id, COUNT(*) as cnt, MAX(created_at) as last FROM memories "
|
|
2508
2508
|
"WHERE category = 'session' AND role != '' "
|
|
2509
|
-
"AND key NOT IN ('llm_output', 'conversation_insight') "
|
|
2509
|
+
"AND key NOT IN ('llm_output', 'llm_input', 'tool_result_raw', 'conversation_insight') "
|
|
2510
2510
|
"GROUP BY session_id ORDER BY last DESC LIMIT 100").fetchall()
|
|
2511
2511
|
sessions = [{"id": r["session_id"], "messages": r["cnt"], "last": r["last"]} for r in rows]
|
|
2512
2512
|
# 批量获取自定义会话名称
|
|
@@ -2559,7 +2559,7 @@ class ApiServer:
|
|
|
2559
2559
|
return web.json_response({**agent_info, "sessions": sessions})
|
|
2560
2560
|
|
|
2561
2561
|
# Internal keys that should not appear in chat history UI
|
|
2562
|
-
_HIDDEN_KEYS = {"llm_output"}
|
|
2562
|
+
_HIDDEN_KEYS = {"llm_output", "llm_input", "tool_result_raw"}
|
|
2563
2563
|
|
|
2564
2564
|
async def handle_get_messages(self, request):
|
|
2565
2565
|
sid = request.match_info["sid"]
|
package/web/ui/index.html
CHANGED
|
@@ -354,7 +354,7 @@ function showConfirm(title,msg,onOk){
|
|
|
354
354
|
<button class="btn btn-ghost" onclick="closeModal()">取消</button></div></div></div>`;
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
-
function showPage(page){
|
|
357
|
+
function showPage(page, addHistory){
|
|
358
358
|
closeMobileSidebar();
|
|
359
359
|
currentPage=page;
|
|
360
360
|
document.querySelectorAll('.nav-item').forEach((n,i)=>n.classList.toggle('active',Object.keys(pages)[i]===page));
|
|
@@ -363,8 +363,69 @@ function showPage(page){
|
|
|
363
363
|
if(renderers[page]){
|
|
364
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>';}
|
|
365
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
|
+
}
|
|
366
394
|
}
|
|
367
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
|
+
|
|
368
429
|
// ========== Dashboard ==========
|
|
369
430
|
async function renderDashboard(){
|
|
370
431
|
const s=await api('/api/status');const m=await api('/api/memory/stats');
|
|
@@ -933,7 +994,8 @@ async function renderSessions(){
|
|
|
933
994
|
}
|
|
934
995
|
async function viewSession(sid){
|
|
935
996
|
window._viewSessionSid=sid;window._viewSessionOffset=0;
|
|
936
|
-
|
|
997
|
+
_navSubState='view:'+sid;
|
|
998
|
+
navigateTo('sessions','view:'+sid,_loadSessionMessages);
|
|
937
999
|
}
|
|
938
1000
|
async function _loadSessionMessages(){
|
|
939
1001
|
const sid=window._viewSessionSid;if(!sid)return;
|
|
@@ -977,17 +1039,25 @@ async function _loadSessionMessages(){
|
|
|
977
1039
|
}
|
|
978
1040
|
html+='</div>';
|
|
979
1041
|
if(hasMore)html+=`<button class="btn btn-ghost mt-8" onclick="window._viewSessionOffset=${offset+100};_loadSessionMessages()">加载更多...</button>`;
|
|
980
|
-
html+='<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="
|
|
1042
|
+
html+='<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="goBack()">返回</button>';
|
|
981
1043
|
html+=`<button class="btn" style="background:var(--accent);color:#fff" onclick="viewSessionRaw('${escHtml(sid)}')">Raw 原始消息</button>`;
|
|
982
1044
|
html+=`<button class="btn btn-primary" onclick="enterSession('${escHtml(sid)}','${escHtml(sid.split('_web_')[0]||'default')}')">在聊天中查看完整记录</button></div>`;
|
|
983
1045
|
$('content').innerHTML=html;
|
|
984
1046
|
}
|
|
985
1047
|
// ========== Raw 原始消息查看 ==========
|
|
986
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
|
+
|
|
987
1057
|
const msgs=await api(`/api/session/raw?sid=${encodeURIComponent(sid)}&limit=5000`);
|
|
988
1058
|
if(!Array.isArray(msgs)){showToast('加载失败','danger');return}
|
|
989
1059
|
// 按时间分组(同秒内合并)
|
|
990
|
-
const keyLabelMap={'llm_output':'LLM 输出','tool_call':'工具调用','tool_result':'工具结果','reasoning':'推理过程','conversation_insight':'会话洞察','':'对话','llm_request':'LLM 请求'};
|
|
1060
|
+
const keyLabelMap={'llm_output':'LLM 输出','llm_input':'LLM 输入','tool_call':'工具调用','tool_result':'工具结果','tool_result_raw':'工具原始数据','reasoning':'推理过程','conversation_insight':'会话洞察','':'对话','llm_request':'LLM 请求'};
|
|
991
1061
|
let html=`<h3 style="margin-bottom:12px">Raw: ${escHtml(sid)} <span class="badge badge-blue">${msgs.length} 条</span></h3>`;
|
|
992
1062
|
// 筛选按钮
|
|
993
1063
|
html+=`<div style="margin-bottom:10px;display:flex;gap:6px;flex-wrap:wrap" id="rawFilterBar">`;
|
|
@@ -1014,9 +1084,11 @@ async function viewSessionRaw(sid){
|
|
|
1014
1084
|
// 颜色标识
|
|
1015
1085
|
let borderColor='var(--border)';
|
|
1016
1086
|
let bgColor='var(--surface)';
|
|
1017
|
-
if(key==='
|
|
1087
|
+
if(key==='llm_input'){borderColor='#06b6d4';bgColor='#001a1f'}
|
|
1088
|
+
else if(key==='llm_output'){borderColor='#e6a817';bgColor='#1a1700'}
|
|
1018
1089
|
else if(key==='tool_call'){borderColor='#3b82f6';bgColor='#001029'}
|
|
1019
1090
|
else if(key==='tool_result'){borderColor='#22c55e';bgColor='#001a0d'}
|
|
1091
|
+
else if(key==='tool_result_raw'){borderColor='#10b981';bgColor='#001510'}
|
|
1020
1092
|
else if(key==='reasoning'){borderColor='#a855f7';bgColor='#0d0020'}
|
|
1021
1093
|
else if(role==='user'){borderColor='var(--primary)';bgColor='var(--surface)'}
|
|
1022
1094
|
else if(role==='assistant'){borderColor='#6b7280';bgColor='var(--surface2)'}
|
|
@@ -1034,8 +1106,8 @@ async function viewSessionRaw(sid){
|
|
|
1034
1106
|
html+=`</div></div>`;
|
|
1035
1107
|
}
|
|
1036
1108
|
html+=`</div>`;
|
|
1037
|
-
html+=`<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="
|
|
1038
|
-
html+=`<button class="btn btn-ghost" onclick="
|
|
1109
|
+
html+=`<div class="flex gap-8 mt-8"><button class="btn btn-ghost" onclick="goBack()">返回查看</button>`;
|
|
1110
|
+
html+=`<button class="btn btn-ghost" onclick="goBack()">返回会话列表</button></div>`;
|
|
1039
1111
|
$('content').innerHTML=html;
|
|
1040
1112
|
// 生成时间索引
|
|
1041
1113
|
_buildTimeNav(msgs);
|
|
@@ -1141,7 +1213,7 @@ async function searchMemory(){
|
|
|
1141
1213
|
}else{
|
|
1142
1214
|
html+='<div class="empty">未找到匹配的记忆</div>';
|
|
1143
1215
|
}
|
|
1144
|
-
html+='<button class="btn btn-ghost mt-8" onclick="
|
|
1216
|
+
html+='<button class="btn btn-ghost mt-8" onclick="goBack()">返回</button>';$('content').innerHTML=html;
|
|
1145
1217
|
}
|
|
1146
1218
|
async function deleteMemory(id){await api(`/api/memory/${id}`,{method:'DELETE'});renderMemory()}
|
|
1147
1219
|
async function cleanupMemory(){const r=await api('/api/memory/cleanup',{method:'POST'});showToast('清理了 '+(r.cleaned||0)+' 条','success');renderMemory()}
|
|
@@ -2066,9 +2138,22 @@ async function sysLoadPreview(){
|
|
|
2066
2138
|
|
|
2067
2139
|
// Init
|
|
2068
2140
|
(function(){
|
|
2069
|
-
var
|
|
2070
|
-
var page=
|
|
2071
|
-
|
|
2141
|
+
var hash=window.location.hash.slice(1)||'';
|
|
2142
|
+
var page=hash?hash.split('~')[0]:'';
|
|
2143
|
+
var sub=hash?hash.slice(page.length+1):'';
|
|
2144
|
+
// 兼容旧 URL query param ?page=xxx
|
|
2145
|
+
if(!page){
|
|
2146
|
+
var params=new URLSearchParams(window.location.search);
|
|
2147
|
+
page=params.get('page')||'dashboard';
|
|
2148
|
+
}
|
|
2149
|
+
if(sub)_navSubState=sub;
|
|
2150
|
+
if(pages[page]){
|
|
2151
|
+
history.replaceState({page:page,sub:sub||null},'','#'+page+(sub?'~'+sub:''));
|
|
2152
|
+
showPage(page,false);
|
|
2153
|
+
}else{
|
|
2154
|
+
history.replaceState({page:'dashboard',sub:null},'','#dashboard');
|
|
2155
|
+
showPage('dashboard',false);
|
|
2156
|
+
}
|
|
2072
2157
|
})();
|
|
2073
2158
|
setInterval(()=>{api('/api/status').catch(()=>{})},30000);
|
|
2074
2159
|
|