mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-21 02:17:21 +02:00
Add files via upload
This commit is contained in:
@@ -2335,6 +2335,75 @@ header {
|
|||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 工具调用状态徽章 */
|
||||||
|
.tool-status-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-left: 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-status-badge.tool-status-running {
|
||||||
|
background: rgba(0, 102, 255, 0.12);
|
||||||
|
color: var(--accent-color);
|
||||||
|
border: 1px solid rgba(0, 102, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-status-badge.tool-status-running::before {
|
||||||
|
content: '';
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--accent-color);
|
||||||
|
display: inline-block;
|
||||||
|
animation: tool-running-pulse 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes tool-running-pulse {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.5;
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-status-badge.tool-status-completed {
|
||||||
|
background: rgba(40, 167, 69, 0.12);
|
||||||
|
color: var(--success-color);
|
||||||
|
border: 1px solid rgba(40, 167, 69, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-status-badge.tool-status-failed {
|
||||||
|
background: rgba(220, 53, 69, 0.12);
|
||||||
|
color: var(--error-color);
|
||||||
|
border: 1px solid rgba(220, 53, 69, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 工具调用项状态样式 */
|
||||||
|
.timeline-item-tool_call.tool-call-running {
|
||||||
|
border-left-color: var(--accent-color);
|
||||||
|
background: rgba(0, 102, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item-tool_call.tool-call-completed {
|
||||||
|
border-left-color: var(--success-color);
|
||||||
|
background: rgba(40, 167, 69, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item-tool_call.tool-call-failed {
|
||||||
|
border-left-color: var(--error-color);
|
||||||
|
background: rgba(220, 53, 69, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
/* 活跃任务栏 */
|
/* 活跃任务栏 */
|
||||||
.active-tasks-bar {
|
.active-tasks-bar {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -4060,7 +4129,7 @@ header {
|
|||||||
.attack-chain-container {
|
.attack-chain-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
background: #ffffff; // 使用纯白色背景,提高节点对比度
|
background: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ let activeTaskInterval = null;
|
|||||||
const ACTIVE_TASK_REFRESH_INTERVAL = 10000; // 10秒检查一次
|
const ACTIVE_TASK_REFRESH_INTERVAL = 10000; // 10秒检查一次
|
||||||
const TASK_FINAL_STATUSES = new Set(['failed', 'timeout', 'cancelled', 'completed']);
|
const TASK_FINAL_STATUSES = new Set(['failed', 'timeout', 'cancelled', 'completed']);
|
||||||
|
|
||||||
|
// 存储工具调用ID到DOM元素的映射,用于更新执行状态
|
||||||
|
const toolCallStatusMap = new Map();
|
||||||
|
|
||||||
const conversationExecutionTracker = {
|
const conversationExecutionTracker = {
|
||||||
activeConversations: new Set(),
|
activeConversations: new Set(),
|
||||||
update(tasks = []) {
|
update(tasks = []) {
|
||||||
@@ -493,12 +496,26 @@ function handleStreamEvent(event, progressElement, progressId,
|
|||||||
const toolName = toolInfo.toolName || '未知工具';
|
const toolName = toolInfo.toolName || '未知工具';
|
||||||
const index = toolInfo.index || 0;
|
const index = toolInfo.index || 0;
|
||||||
const total = toolInfo.total || 0;
|
const total = toolInfo.total || 0;
|
||||||
addTimelineItem(timeline, 'tool_call', {
|
const toolCallId = toolInfo.toolCallId || null;
|
||||||
|
|
||||||
|
// 添加工具调用项,并标记为执行中
|
||||||
|
const toolCallItemId = addTimelineItem(timeline, 'tool_call', {
|
||||||
title: `🔧 调用工具: ${escapeHtml(toolName)} (${index}/${total})`,
|
title: `🔧 调用工具: ${escapeHtml(toolName)} (${index}/${total})`,
|
||||||
message: event.message,
|
message: event.message,
|
||||||
data: toolInfo,
|
data: toolInfo,
|
||||||
expanded: false
|
expanded: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 如果有toolCallId,存储映射关系以便后续更新状态
|
||||||
|
if (toolCallId && toolCallItemId) {
|
||||||
|
toolCallStatusMap.set(toolCallId, {
|
||||||
|
itemId: toolCallItemId,
|
||||||
|
timeline: timeline
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加执行中状态指示器
|
||||||
|
updateToolCallStatus(toolCallId, 'running');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'tool_result':
|
case 'tool_result':
|
||||||
@@ -507,6 +524,15 @@ function handleStreamEvent(event, progressElement, progressId,
|
|||||||
const resultToolName = resultInfo.toolName || '未知工具';
|
const resultToolName = resultInfo.toolName || '未知工具';
|
||||||
const success = resultInfo.success !== false;
|
const success = resultInfo.success !== false;
|
||||||
const statusIcon = success ? '✅' : '❌';
|
const statusIcon = success ? '✅' : '❌';
|
||||||
|
const resultToolCallId = resultInfo.toolCallId || null;
|
||||||
|
|
||||||
|
// 如果有关联的toolCallId,更新工具调用项的状态
|
||||||
|
if (resultToolCallId && toolCallStatusMap.has(resultToolCallId)) {
|
||||||
|
updateToolCallStatus(resultToolCallId, success ? 'completed' : 'failed');
|
||||||
|
// 从映射中移除(已完成)
|
||||||
|
toolCallStatusMap.delete(resultToolCallId);
|
||||||
|
}
|
||||||
|
|
||||||
addTimelineItem(timeline, 'tool_result', {
|
addTimelineItem(timeline, 'tool_result', {
|
||||||
title: `${statusIcon} 工具 ${escapeHtml(resultToolName)} 执行${success ? '完成' : '失败'}`,
|
title: `${statusIcon} 工具 ${escapeHtml(resultToolName)} 执行${success ? '完成' : '失败'}`,
|
||||||
message: event.message,
|
message: event.message,
|
||||||
@@ -767,9 +793,46 @@ function handleStreamEvent(event, progressElement, progressId,
|
|||||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新工具调用状态
|
||||||
|
function updateToolCallStatus(toolCallId, status) {
|
||||||
|
const mapping = toolCallStatusMap.get(toolCallId);
|
||||||
|
if (!mapping) return;
|
||||||
|
|
||||||
|
const item = document.getElementById(mapping.itemId);
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
|
const titleElement = item.querySelector('.timeline-item-title');
|
||||||
|
if (!titleElement) return;
|
||||||
|
|
||||||
|
// 移除之前的状态类
|
||||||
|
item.classList.remove('tool-call-running', 'tool-call-completed', 'tool-call-failed');
|
||||||
|
|
||||||
|
// 根据状态更新样式和文本
|
||||||
|
let statusText = '';
|
||||||
|
if (status === 'running') {
|
||||||
|
item.classList.add('tool-call-running');
|
||||||
|
statusText = ' <span class="tool-status-badge tool-status-running">执行中...</span>';
|
||||||
|
} else if (status === 'completed') {
|
||||||
|
item.classList.add('tool-call-completed');
|
||||||
|
statusText = ' <span class="tool-status-badge tool-status-completed">✅ 已完成</span>';
|
||||||
|
} else if (status === 'failed') {
|
||||||
|
item.classList.add('tool-call-failed');
|
||||||
|
statusText = ' <span class="tool-status-badge tool-status-failed">❌ 执行失败</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新标题(保留原有文本,追加状态)
|
||||||
|
const originalText = titleElement.innerHTML;
|
||||||
|
// 移除之前可能存在的状态标记
|
||||||
|
const cleanText = originalText.replace(/\s*<span class="tool-status-badge[^>]*>.*?<\/span>/g, '');
|
||||||
|
titleElement.innerHTML = cleanText + statusText;
|
||||||
|
}
|
||||||
|
|
||||||
// 添加时间线项目
|
// 添加时间线项目
|
||||||
function addTimelineItem(timeline, type, options) {
|
function addTimelineItem(timeline, type, options) {
|
||||||
const item = document.createElement('div');
|
const item = document.createElement('div');
|
||||||
|
// 生成唯一ID
|
||||||
|
const itemId = 'timeline-item-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
|
||||||
|
item.id = itemId;
|
||||||
item.className = `timeline-item timeline-item-${type}`;
|
item.className = `timeline-item timeline-item-${type}`;
|
||||||
|
|
||||||
const time = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
const time = new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
||||||
@@ -828,6 +891,9 @@ function addTimelineItem(timeline, type, options) {
|
|||||||
if (!expanded && (type === 'tool_call' || type === 'tool_result')) {
|
if (!expanded && (type === 'tool_call' || type === 'tool_result')) {
|
||||||
// 对于工具调用和结果,默认显示摘要
|
// 对于工具调用和结果,默认显示摘要
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 返回item ID以便后续更新
|
||||||
|
return itemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载活跃任务列表
|
// 加载活跃任务列表
|
||||||
|
|||||||
Reference in New Issue
Block a user