feat: 优化智能体卡片和工具显示

- 添加智能体卡片智能滚动功能:自动滚动到底部,用户向上滚动时停止,滚动到底部恢复
   - 过滤 spawnExplorer 工具,不在界面显示
   - 添加所有工具的中文名称映射(file_read、file_write、queryRules、setModule 等)
   - 优化代码结构,移除未使用的导入
This commit is contained in:
Roe-xin
2025-12-30 22:51:15 +08:00
parent 842e5fb49b
commit d43cd610a0
3 changed files with 152 additions and 391 deletions

View File

@ -70,3 +70,9 @@ export const stopIconSvg = `
<path d="M349.75 349.75m57.15 0l210.2 0q57.15 0 57.15 57.15l0 210.2q0 57.15-57.15 57.15l-210.2 0q-57.15 0-57.15-57.15l0-210.2q0-57.15 57.15-57.15Z" fill="currentColor"></path> <path d="M349.75 349.75m57.15 0l210.2 0q57.15 0 57.15 57.15l0 210.2q0 57.15-57.15 57.15l-210.2 0q-57.15 0-57.15-57.15l0-210.2q0-57.15 57.15-57.15Z" fill="currentColor"></path>
</svg> </svg>
`; `;
/**
* 探索智能体图标 SVG
*/
export const agentIconSvg = `
<svg t="1767101071638" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7779" width="16" height="16" style="display: inline-block; vertical-align: middle;"><path d="M173.474909 410.414545c-20.293818 0-33.838545-13.498182-33.838545-33.792v-135.377454C139.636364 187.066182 187.019636 139.636364 241.198545 139.636364h135.447273c20.270545 0 33.815273 13.591273 33.815273 33.885091s-13.591273 33.838545-33.885091 33.838545h-135.447273c-20.317091 0-33.815273 13.591273-33.815272 33.885091v135.377454c0.046545 20.293818-13.498182 33.792-33.838546 33.792z m203.101091 473.902546h-135.447273C187.042909 884.317091 139.636364 836.933818 139.636364 782.754909V647.447273c0-20.386909 13.544727-33.838545 33.838545-33.838546s33.885091 13.451636 33.885091 33.838546v135.330909c0 20.293818 13.544727 33.931636 33.838545 33.931636h135.447273c20.270545 0 33.815273 13.451636 33.815273 33.745455-0.046545 20.340364-13.591273 33.885091-33.885091 33.885091z m406.178909 0H647.447273c-20.386909 0-33.931636-13.544727-33.931637-33.931636 0-20.293818 13.544727-33.745455 33.931637-33.745455h135.330909c20.386909 0 33.838545-13.637818 33.838545-33.931636V647.447273c0-20.386909 13.544727-33.838545 33.931637-33.838546 20.293818 0 33.838545 13.451636 33.838545 33.838546v135.330909c-0.046545 54.178909-47.522909 101.562182-101.608727 101.562182z m67.723636-473.902546c-20.386909 0-33.931636-13.498182-33.931636-33.792v-135.377454c0-20.340364-13.451636-33.885091-33.838545-33.885091H647.447273c-20.386909 0-33.931636-13.498182-33.931637-33.838545S627.083636 139.636364 647.424 139.636364h135.330909c54.085818 0 101.562182 47.429818 101.562182 101.608727v135.377454c0 20.293818-13.544727 33.792-33.838546 33.792z m0 135.493819H173.474909c-20.293818 0-33.838545-13.591273-33.838545-33.931637s13.544727-33.885091 33.838545-33.885091h677.003636c20.293818 0 33.838545 13.591273 33.838546 33.885091s-13.544727 33.931636-33.838546 33.931637z" fill="#8a8a8a" p-id="7780"></path></svg>`;

View File

@ -2,310 +2,176 @@
* 智能体卡片组件 * 智能体卡片组件
* *
* 功能说明: * 功能说明:
* - 显示子智能体执行过程 * - 提供智能体执行状态的可视化展示
* - 支持展开/收起步骤详情 * - 显示智能体名称、状态和执行步骤
* - 显示执行状态和统计信息 * - 支持实时更新步骤信息
*/ */
import type { import { agentIconSvg } from "../constants/toolIcons";
AgentStartEvent,
AgentProgressEvent,
AgentCompleteEvent,
AgentErrorEvent
} from '../types/api';
/** /**
* 获取智能体卡片样式 * 获取智能体卡片样式
*/ */
export function getAgentCardStyles(): string { export function getAgentCardStyles(): string {
return ` return `
/* 智能体卡片样式 */
.segment-agent {
margin: 8px 0;
}
.agent-card { .agent-card {
background: var(--vscode-editor-background);
border: 1px solid var(--vscode-input-border); border: 1px solid var(--vscode-input-border);
border-radius: 8px; border-radius: 8px;
margin: 10px 0;
overflow: hidden; overflow: hidden;
background: var(--vscode-editor-background);
} }
.agent-card-header { .agent-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
background: var(--vscode-sideBar-background);
cursor: pointer;
user-select: none;
}
.agent-card-header:hover {
background: var(--vscode-list-hoverBackground);
}
.agent-card-title {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
font-weight: 500; padding: 8px 12px;
background: var(--vscode-sideBar-background);
border-bottom: 1px solid var(--vscode-input-border);
} }
.agent-card-icon { .agent-icon {
font-size: 16px; font-size: 16px;
} }
.agent-card-status { .agent-name {
font-size: 12px; font-weight: 500;
padding: 2px 6px; flex: 1;
border-radius: 4px;
} }
.agent-card-status.running { .agent-status {
font-size: 11px;
padding: 2px 8px;
border-radius: 10px;
}
.agent-status.running {
background: var(--vscode-inputValidation-infoBackground); background: var(--vscode-inputValidation-infoBackground);
color: var(--vscode-inputValidation-infoForeground); color: var(--vscode-inputValidation-infoForeground);
} }
.agent-card-status.completed { .agent-status.completed {
background: var(--vscode-testing-iconPassed); background: #28a745;
color: white; color: white;
} }
.agent-card-status.error { .agent-status.error {
background: var(--vscode-testing-iconFailed); background: #dc3545;
color: white; color: white;
} }
.agent-card-toggle { .agent-body {
padding: 8px;
}
.agent-steps-container {
max-height: 150px;
overflow-y: auto;
font-size: 12px; font-size: 12px;
color: var(--vscode-descriptionForeground);
}
.agent-card-body {
padding: 12px;
border-top: 1px solid var(--vscode-input-border);
}
.agent-card-body.collapsed {
display: none;
}
.agent-card-instruction {
font-size: 13px;
color: var(--vscode-descriptionForeground);
margin-bottom: 10px;
padding-bottom: 10px;
border-bottom: 1px dashed var(--vscode-input-border);
}
.agent-steps {
font-size: 13px;
} }
.agent-step { .agent-step {
display: flex; display: flex;
align-items: flex-start; align-items: center;
gap: 8px; gap: 6px;
padding: 6px 0; padding: 4px 8px;
border-left: 2px solid var(--vscode-input-border); border-radius: 4px;
padding-left: 12px; margin-bottom: 4px;
margin-left: 6px; background: var(--vscode-list-hoverBackground);
} }
.agent-step:last-child { .agent-step:last-child {
border-left-color: transparent; margin-bottom: 0;
} }
.agent-step-icon { .step-icon {
flex-shrink: 0; flex-shrink: 0;
} }
.agent-step-content { .step-name {
flex: 1;
min-width: 0;
}
.agent-step-name {
font-weight: 500; font-weight: 500;
color: var(--vscode-foreground);
} }
.agent-step-result { .step-result {
font-size: 12px;
color: var(--vscode-descriptionForeground); color: var(--vscode-descriptionForeground);
margin-top: 2px; font-size: 11px;
white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap;
} }
.agent-card-summary { .agent-step-placeholder {
font-size: 13px; color: var(--vscode-descriptionForeground);
padding: 8px 12px; font-style: italic;
background: var(--vscode-sideBar-background); padding: 8px;
border-top: 1px solid var(--vscode-input-border); text-align: center;
}
.agent-card-error {
color: var(--vscode-errorForeground);
padding: 8px 12px;
background: var(--vscode-inputValidation-errorBackground);
} }
`; `;
} }
/** /**
* 渲染智能体卡片(启动状态) * 获取智能体卡片的脚本
*/
export function renderAgentCardStart(event: AgentStartEvent): string {
return `
<div class="agent-card" id="agent-${event.agentId}">
<div class="agent-card-header" onclick="toggleAgentCard('${event.agentId}')">
<div class="agent-card-title">
<span class="agent-card-icon">🤖</span>
<span>${event.agentName}</span>
<span class="agent-card-status running">执行中</span>
</div>
<span class="agent-card-toggle">▼</span>
</div>
<div class="agent-card-body" id="agent-body-${event.agentId}">
<div class="agent-card-instruction">指令:${escapeHtml(event.instruction)}</div>
<div class="agent-steps" id="agent-steps-${event.agentId}">
<!-- 步骤将动态添加 -->
</div>
</div>
</div>
`;
}
/**
* 渲染步骤项(进行中)
*/
export function renderAgentStepRunning(event: AgentProgressEvent): string {
const inputStr = event.toolInput ? JSON.stringify(event.toolInput) : '';
const shortInput = inputStr.length > 50 ? inputStr.substring(0, 50) + '...' : inputStr;
return `
<div class="agent-step" id="agent-step-${event.agentId}-${event.step}">
<span class="agent-step-icon">🔄</span>
<div class="agent-step-content">
<div class="agent-step-name">${event.toolName}</div>
<div class="agent-step-result">${escapeHtml(shortInput)}</div>
</div>
</div>
`;
}
/**
* 更新步骤项(完成)
*/
export function getStepCompleteUpdate(event: AgentProgressEvent): { icon: string; result: string } {
const result = event.toolResult || '';
const shortResult = result.length > 80 ? result.substring(0, 80) + '...' : result;
return {
icon: event.status === 'completed' ? '✅' : '❌',
result: shortResult
};
}
/**
* 获取智能体卡片脚本
*/ */
export function getAgentCardScript(): string { export function getAgentCardScript(): string {
return ` return `
// 智能体状态存储 // 工具名称中文映射
const agentStates = {}; function getAgentToolDisplayName(toolName) {
const toolNameMap = {
// 切换智能体卡片展开/收起 'file_read': '文件读取',
function toggleAgentCard(agentId) { 'file_write': '文件写入',
const body = document.getElementById('agent-body-' + agentId); 'file_delete': '文件删除',
const header = body?.previousElementSibling; 'file_list': '检索文件',
const toggle = header?.querySelector('.agent-card-toggle'); 'syntax_check': '语法检查',
'simulation': '仿真',
if (body && toggle) { 'waveform_summary': '波形分析',
body.classList.toggle('collapsed'); 'knowledge_save': '保存知识库',
toggle.textContent = body.classList.contains('collapsed') ? '▶' : '▼'; 'knowledge_load': '加载知识库',
} 'queryKnowledgeSummary': '查询知识摘要',
} 'queryRules': '查询规则',
'setModule': '设置模块',
// 处理智能体启动事件 'addSignal': '添加信号',
function handleAgentStart(event) { 'addSignalExample': '添加信号示例',
agentStates[event.agentId] = { 'validateKnowledgeGraph': '验证知识图谱',
status: 'running', 'querySignals': '查询信号',
steps: [] 'addPlan': '添加计划',
'addEdge': '添加边',
'showPlan': '显示计划',
'spawnExplorer': '代码探索'
}; };
return toolNameMap[toolName] || toolName;
// 在当前消息中添加智能体卡片
const currentMessage = document.querySelector('.bot-message:last-child .message-content');
if (currentMessage) {
currentMessage.insertAdjacentHTML('beforeend', renderAgentCardStart(event));
}
}
// 处理智能体进度事件
function handleAgentProgress(event) {
const stepsContainer = document.getElementById('agent-steps-' + event.agentId);
if (!stepsContainer) return;
if (event.status === 'running') {
// 添加新步骤
stepsContainer.insertAdjacentHTML('beforeend', renderAgentStepRunning(event));
} else if (event.status === 'completed') {
// 更新步骤状态
const stepEl = document.getElementById('agent-step-' + event.agentId + '-' + event.step);
if (stepEl) {
const iconEl = stepEl.querySelector('.agent-step-icon');
const resultEl = stepEl.querySelector('.agent-step-result');
if (iconEl) iconEl.textContent = '✅';
if (resultEl) {
const result = event.toolResult || '';
resultEl.textContent = result.length > 80 ? result.substring(0, 80) + '...' : result;
}
}
}
}
// 处理智能体完成事件
function handleAgentComplete(event) {
const card = document.getElementById('agent-' + event.agentId);
if (!card) return;
// 更新状态
const statusEl = card.querySelector('.agent-card-status');
if (statusEl) {
statusEl.className = 'agent-card-status completed';
statusEl.textContent = '完成';
}
// 添加摘要
const body = card.querySelector('.agent-card-body');
if (body) {
body.insertAdjacentHTML('beforeend',
'<div class="agent-card-summary">' + escapeHtml(event.summary) + '</div>'
);
}
// 自动收起
body?.classList.add('collapsed');
const toggle = card.querySelector('.agent-card-toggle');
if (toggle) toggle.textContent = '▶';
}
// 处理智能体错误事件
function handleAgentError(event) {
const card = document.getElementById('agent-' + event.agentId);
if (!card) return;
// 更新状态
const statusEl = card.querySelector('.agent-card-status');
if (statusEl) {
statusEl.className = 'agent-card-status error';
statusEl.textContent = '错误';
}
// 添加错误信息
const body = card.querySelector('.agent-card-body');
if (body) {
body.insertAdjacentHTML('beforeend',
'<div class="agent-card-error">错误:' + escapeHtml(event.error) + '</div>'
);
}
}
// HTML 转义
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
`;
} }
/** /**
* HTML 转义(服务端使用) * 渲染智能体卡片
* @param {Object} segment - 智能体段落数据
* @param {HTMLElement} segmentDiv - 段落容器元素
*/ */
function escapeHtml(text: string): string { function renderAgentCard(segment, segmentDiv) {
if (!text) return ''; segmentDiv.className += ' segment-agent';
return text
.replace(/&/g, '&amp;') const statusText = segment.agentStatus === 'completed' ? '完成'
.replace(/</g, '&lt;') : segment.agentStatus === 'error' ? '错误' : '执行中';
.replace(/>/g, '&gt;') const statusClass = segment.agentStatus || 'running';
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;'); const stepsHtml = (segment.agentSteps || []).map(step => {
const icon = step.status === 'completed' ? '✅' : step.status === 'error' ? '❌' : '🔄';
const displayName = getAgentToolDisplayName(step.toolName);
const result = step.toolResult ? \`: \${step.toolResult.substring(0, 50)}\${step.toolResult.length > 50 ? '...' : ''}\` : '';
return \`<div class="agent-step"><span class="step-icon">\${icon}</span><span class="step-name">\${displayName}</span><span class="step-result">\${result}</span></div>\`;
}).join('');
segmentDiv.innerHTML = \`
<div class="agent-card">
<div class="agent-header">
<span class="agent-icon">${agentIconSvg}</span>
<span class="agent-name">\${segment.agentName || '智能体'}</span>
<span class="agent-status \${statusClass}">\${statusText}</span>
</div>
<div class="agent-body">
<div class="agent-steps-container">
\${stepsHtml || '<div class="agent-step-placeholder">等待执行...</div>'}
</div>
</div>
</div>
\`;
// 自动滚动到最新步骤
setTimeout(() => {
const container = segmentDiv.querySelector('.agent-steps-container');
if (container) {
container.scrollTop = container.scrollHeight;
}
}, 0);
}
`;
} }

View File

@ -15,11 +15,13 @@ import {
fileWriteIconSvg, fileWriteIconSvg,
syntaxCheckIconSvg, syntaxCheckIconSvg,
SearchCode, SearchCode,
agentIconSvg,
} from "../constants/toolIcons"; } from "../constants/toolIcons";
import { import {
getWaveformPreviewContent, getWaveformPreviewContent,
getWaveformPreviewScript, getWaveformPreviewScript,
} from "./waveformPreviewContent"; } from "./waveformPreviewContent";
import { getAgentCardStyles, getAgentCardScript } from "./agentCard";
/** /**
* 获取消息区域的 HTML 内容 * 获取消息区域的 HTML 内容
@ -528,88 +530,7 @@ export function getMessageAreaStyles(): string {
border-radius: 4px; border-radius: 4px;
font-size: 12px;} font-size: 12px;}
/* 智能体卡片样式 */ ${getAgentCardStyles()}
.segment-agent {
margin: 8px 0;
}
.agent-card {
border: 1px solid var(--vscode-input-border);
border-radius: 8px;
overflow: hidden;
background: var(--vscode-editor-background);
}
.agent-header {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
background: var(--vscode-sideBar-background);
border-bottom: 1px solid var(--vscode-input-border);
}
.agent-icon {
font-size: 16px;
}
.agent-name {
font-weight: 500;
flex: 1;
}
.agent-status {
font-size: 11px;
padding: 2px 8px;
border-radius: 10px;
}
.agent-status.running {
background: var(--vscode-inputValidation-infoBackground);
color: var(--vscode-inputValidation-infoForeground);
}
.agent-status.completed {
background: #28a745;
color: white;
}
.agent-status.error {
background: #dc3545;
color: white;
}
.agent-body {
padding: 8px;
}
.agent-steps-container {
max-height: 150px;
overflow-y: auto;
font-size: 12px;
}
.agent-step {
display: flex;
align-items: center;
gap: 6px;
padding: 4px 8px;
border-radius: 4px;
margin-bottom: 4px;
background: var(--vscode-list-hoverBackground);
}
.agent-step:last-child {
margin-bottom: 0;
}
.step-icon {
flex-shrink: 0;
}
.step-name {
font-weight: 500;
color: var(--vscode-foreground);
}
.step-result {
color: var(--vscode-descriptionForeground);
font-size: 11px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.agent-step-placeholder {
color: var(--vscode-descriptionForeground);
font-style: italic;
padding: 8px;
text-align: center;
}
/* 计划卡片样式 */ /* 计划卡片样式 */
.segment-plan { .segment-plan {
@ -708,15 +629,31 @@ export function getMessageAreaScript(): string {
const syntaxCheckIconSvg = \`${syntaxCheckIconSvg}\`; const syntaxCheckIconSvg = \`${syntaxCheckIconSvg}\`;
const searchCodeIconSvg = \`${SearchCode}\`; const searchCodeIconSvg = \`${SearchCode}\`;
${getAgentCardScript()}
// 工具名称映射 // 工具名称映射
function getToolDisplayName(toolName) { function getToolDisplayName(toolName) {
const toolNameMap = { const toolNameMap = {
'file_read': '已完成文件读取', 'file_read': '已完成文件读取',
'file_write': '已完成文件写入', 'file_write': '已完成文件写入',
'file_delete': '已完成文件删除',
'file_list': '已检索代码文件', 'file_list': '已检索代码文件',
'syntax_check': '已完成语法检查', 'syntax_check': '已完成语法检查',
'simulation': '已完成仿真', 'simulation': '已完成仿真',
'waveform_summary': '已完成波形分析' 'waveform_summary': '已完成波形分析',
'knowledge_save': '已保存知识库',
'knowledge_load': '已加载知识库',
'queryKnowledgeSummary': '已查询知识摘要',
'queryRules': '已查询规则',
'setModule': '已设置模块',
'addSignal': '已添加信号',
'addSignalExample': '已添加信号示例',
'validateKnowledgeGraph': '已验证知识图谱',
'querySignals': '已查询信号',
'addPlan': '已添加计划',
'addEdge': '已添加边',
'showPlan': '已显示计划',
'spawnExplorer': '代码探索'
}; };
return toolNameMap[toolName] || toolName; return toolNameMap[toolName] || toolName;
} }
@ -949,6 +886,10 @@ export function getMessageAreaScript(): string {
segmentDiv.className += ' segment-text'; segmentDiv.className += ' segment-text';
segmentDiv.innerHTML = formatText(segment.content); segmentDiv.innerHTML = formatText(segment.content);
} else if (segment.type === 'tool') { } else if (segment.type === 'tool') {
// 过滤掉不需要显示的工具
if (segment.toolName === 'spawnExplorer') {
return;
}
const statusIcon = segment.toolStatus === 'error' ? '❌' : '🔧'; const statusIcon = segment.toolStatus === 'error' ? '❌' : '🔧';
const toolResult = segment.toolResult || ''; const toolResult = segment.toolResult || '';
@ -1083,39 +1024,7 @@ export function getMessageAreaScript(): string {
} }
} else if (segment.type === 'agent') { } else if (segment.type === 'agent') {
// 智能体卡片渲染 // 智能体卡片渲染
segmentDiv.className += ' segment-agent'; renderAgentCard(segment, segmentDiv);
const statusText = segment.agentStatus === 'completed' ? '完成'
: segment.agentStatus === 'error' ? '错误' : '执行中';
const statusClass = segment.agentStatus || 'running';
const stepsHtml = (segment.agentSteps || []).map(step => {
const icon = step.status === 'completed' ? '✅' : step.status === 'error' ? '❌' : '🔄';
const result = step.toolResult ? \`: \${step.toolResult.substring(0, 50)}\${step.toolResult.length > 50 ? '...' : ''}\` : '';
return \`<div class="agent-step"><span class="step-icon">\${icon}</span><span class="step-name">\${step.toolName}</span><span class="step-result">\${result}</span></div>\`;
}).join('');
segmentDiv.innerHTML = \`
<div class="agent-card">
<div class="agent-header">
<span class="agent-icon">🤖</span>
<span class="agent-name">\${segment.agentName || '智能体'}</span>
<span class="agent-status \${statusClass}">\${statusText}</span>
</div>
<div class="agent-body">
<div class="agent-steps-container">
\${stepsHtml || '<div class="agent-step-placeholder">等待执行...</div>'}
</div>
</div>
</div>
\`;
// 自动滚动到最新步骤
setTimeout(() => {
const container = segmentDiv.querySelector('.agent-steps-container');
if (container) {
container.scrollTop = container.scrollHeight;
}
}, 0);
} else if (segment.type === 'plan') { } else if (segment.type === 'plan') {
// 计划卡片渲染(类似 askUser // 计划卡片渲染(类似 askUser
segmentDiv.className += ' segment-plan'; segmentDiv.className += ' segment-plan';
@ -1269,6 +1178,10 @@ export function getMessageAreaScript(): string {
segmentDiv.className += ' segment-text'; segmentDiv.className += ' segment-text';
segmentDiv.innerHTML = formatText(segment.content); segmentDiv.innerHTML = formatText(segment.content);
} else if (segment.type === 'tool') { } else if (segment.type === 'tool') {
// 过滤掉不需要显示的工具
if (segment.toolName === 'spawnExplorer') {
return;
}
const statusIcon = segment.toolStatus === 'error' ? '❌' : '🔧'; const statusIcon = segment.toolStatus === 'error' ? '❌' : '🔧';
const toolResult = segment.toolResult || ''; const toolResult = segment.toolResult || '';
@ -1347,31 +1260,7 @@ export function getMessageAreaScript(): string {
\`; \`;
} else if (segment.type === 'agent') { } else if (segment.type === 'agent') {
// 智能体卡片渲染 // 智能体卡片渲染
segmentDiv.className += ' segment-agent'; renderAgentCard(segment, segmentDiv);
const statusText = segment.agentStatus === 'completed' ? '完成'
: segment.agentStatus === 'error' ? '错误' : '执行中';
const statusClass = segment.agentStatus || 'running';
const stepsHtml = (segment.agentSteps || []).map(step => {
const icon = step.status === 'completed' ? '✅' : step.status === 'error' ? '❌' : '🔄';
const result = step.toolResult ? \`: \${step.toolResult.substring(0, 50)}\${step.toolResult.length > 50 ? '...' : ''}\` : '';
return \`<div class="agent-step"><span class="step-icon">\${icon}</span><span class="step-name">\${step.toolName}</span><span class="step-result">\${result}</span></div>\`;
}).join('');
segmentDiv.innerHTML = \`
<div class="agent-card">
<div class="agent-header">
<span class="agent-icon">🤖</span>
<span class="agent-name">\${segment.agentName || '智能体'}</span>
<span class="agent-status \${statusClass}">\${statusText}</span>
</div>
<div class="agent-body">
<div class="agent-steps-container">
\${stepsHtml || '<div class="agent-step-placeholder">等待执行...</div>'}
</div>
</div>
</div>
\`;
} else if (segment.type === 'plan') { } else if (segment.type === 'plan') {
// 计划卡片渲染 // 计划卡片渲染
segmentDiv.className += ' segment-plan'; segmentDiv.className += ' segment-plan';