// 状态
let currentAgent = null;
let currentSession = null;
let currentMessage = null;
let currentView = 'conversations'; // 'conversations' or 'sessions'
let conversationsData = []; // 缓存对话汇总数据
// API 调用
async function fetchAPI(endpoint) {
const response = await fetch(`/api${endpoint}`);
if (!response.ok) {
throw new Error(`API Error: ${response.status}`);
}
return response.json();
}
// 格式化时间
function formatTime(isoString) {
if (!isoString) return '-';
const date = new Date(isoString);
return date.toLocaleString('zh-CN', {
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}
function formatFullTime(isoString) {
if (!isoString) return '-';
const date = new Date(isoString);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
}
// 格式化数字
function formatNumber(num) {
if (!num) return '0';
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
return num.toString();
}
// 截断文本
function truncate(text, maxLen = 50) {
if (!text) return '';
text = text.replace(/\n/g, ' ').trim();
if (text.length <= maxLen) return text;
return text.substring(0, maxLen) + '...';
}
// 加载智能体列表
async function loadAgents() {
const container = document.getElementById('agents-list');
container.innerHTML = '
加载中...
';
try {
const agents = await fetchAPI('/agents');
if (agents.length === 0) {
container.innerHTML = '没有找到智能体
';
return;
}
container.innerHTML = agents.map(agent => `
🤖 ${agent.name}
💬 ${agent.sessionCount}
${formatTime(agent.lastActive)}
`).join('');
} catch (error) {
container.innerHTML = `加载失败: ${error.message}
`;
}
}
// 切换视图
function switchView(view) {
currentView = view;
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.toggle('active', btn.dataset.view === view);
});
document.querySelectorAll('.view-content').forEach(content => {
content.classList.remove('active');
});
document.getElementById(`${view}-view`).classList.add('active');
}
// 选择智能体
async function selectAgent(agentName) {
currentAgent = agentName;
currentSession = null;
currentMessage = null;
// 更新UI
document.querySelectorAll('.agent-item').forEach(el => el.classList.remove('active'));
event.target.closest('.agent-item')?.classList.add('active');
document.getElementById('agent-name-display').textContent = `🤖 ${agentName}`;
document.getElementById('session-id-display').textContent = '';
document.getElementById('messages-list').innerHTML = '请选择一个会话
';
document.getElementById('message-detail').innerHTML = '请选择一条消息
';
// 同时加载对话汇总和会话列表
await Promise.all([
loadConversations(agentName),
loadSessions(agentName)
]);
}
// 加载会话列表
async function loadSessions(agentName) {
const container = document.getElementById('sessions-list');
container.innerHTML = '加载中...
';
try {
const sessions = await fetchAPI(`/agents/${agentName}/sessions`);
if (sessions.length === 0) {
container.innerHTML = '没有找到会话
';
return;
}
container.innerHTML = sessions.map(session => `
${session.model}
${formatTime(session.updatedAt)}
${truncate(session.target, 40)}
📊 ${formatNumber(session.totalTokens)} tokens
(${formatNumber(session.inputTokens)} in / ${formatNumber(session.outputTokens)} out)
`).join('');
} catch (error) {
container.innerHTML = `加载失败: ${error.message}
`;
}
}
// 选择会话 - 显示消息概览列表
async function selectSession(agentName, sessionId) {
currentSession = sessionId;
currentMessage = null;
// 更新UI
document.querySelectorAll('.session-item').forEach(el => el.classList.remove('active'));
event.target.closest('.session-item')?.classList.add('active');
document.getElementById('session-id-display').textContent = `- ${sessionId.substring(0, 8)}...`;
document.getElementById('message-detail').innerHTML = '请选择一条消息查看详情
';
// 加载消息概览列表
await loadMessageSummaries(agentName, sessionId);
}
// 加载消息概览列表(不加载完整内容)
async function loadMessageSummaries(agentName, sessionId) {
const container = document.getElementById('messages-list');
container.innerHTML = '加载中...
';
try {
const messages = await fetchAPI(`/agents/${agentName}/sessions/${sessionId}/messages`);
if (messages.length === 0) {
container.innerHTML = '没有找到消息
';
return;
}
container.innerHTML = messages.map((msg, index) => `
${escapeHtml(msg.summary)}${msg.hasMoreContent ? '...' : ''}
${msg.hasMoreContent ? `📝 ${formatNumber(msg.contentLength)} 字符` : ''}
`).join('');
} catch (error) {
container.innerHTML = `加载失败: ${error.message}
`;
}
}
// 选择消息 - 显示完整内容
async function selectMessage(agentName, sessionId, messageId) {
currentMessage = messageId;
// 更新UI
document.querySelectorAll('.message-summary').forEach(el => el.classList.remove('active'));
event.target.closest('.message-summary')?.classList.add('active');
// 加载完整消息内容
await loadMessageDetail(agentName, sessionId, messageId);
}
// 加载消息详情(完整内容)
async function loadMessageDetail(agentName, sessionId, messageId) {
const container = document.getElementById('message-detail');
container.innerHTML = '加载中...
';
try {
const msg = await fetchAPI(`/agents/${agentName}/sessions/${sessionId}/messages/${messageId}`);
container.innerHTML = `
${escapeHtml(msg.content)}
`;
} catch (error) {
container.innerHTML = `加载失败: ${error.message}
`;
}
}
// HTML 转义
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 键盘事件
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
// 可以添加关闭操作
}
});
// 加载对话汇总
async function loadConversations(agentName) {
const container = document.getElementById('conversations-list');
container.innerHTML = '加载中...
';
try {
const conversations = await fetchAPI(`/agents/${agentName}/conversations`);
conversationsData = conversations;
if (conversations.length === 0) {
container.innerHTML = '没有找到对话
';
return;
}
container.innerHTML = conversations.map((conv, index) => `
📨 消息: ${conv.totalMessages}
📊 Token: ${formatNumber(conv.totalTokens)}
🔄 压缩: ${conv.compactionCount}
⏱️ 时长: ${conv.durationHours || '?'}h
${conv.channel} · ${conv.chatType} · ${truncate(conv.target, 30)}
${formatTime(conv.firstStartedAt)} → ${formatTime(conv.lastUpdatedAt)}
`).join('');
} catch (error) {
container.innerHTML = `加载失败: ${error.message}
`;
}
}
// 显示对话详情(包含该对话下的所有 session)
function showConversationDetail(index) {
const conv = conversationsData[index];
if (!conv) return;
// 高亮选中的对话
document.querySelectorAll('.conversation-item').forEach((el, i) => {
el.classList.toggle('active', i === index);
});
// 切换到会话视图并显示该对话下的 session
switchView('sessions');
const container = document.getElementById('sessions-list');
container.innerHTML = `
${conv.sessions.map((session, sIndex) => `
${session.model}
${formatTime(session.startedAt)}
📊 ${formatNumber(session.totalTokens)} tokens · 📨 ${session.messageCount} 条消息
${formatTime(session.startedAt)} → ${formatTime(session.updatedAt)}
`).join('')}
`;
}
// 返回对话汇总
function backToConversations() {
switchView('conversations');
document.querySelectorAll('.conversation-item').forEach(el => el.classList.remove('active'));
}
// 初始化
loadAgents();