feat: 增加失败历史详情渲染功能,展示失败反馈信息

This commit is contained in:
catlog22
2026-01-21 18:32:52 +08:00
parent a7c8ea04f1
commit 82b8fcc608
2 changed files with 142 additions and 2 deletions

View File

@@ -331,6 +331,79 @@
word-break: break-word;
}
/* Failure History Detail */
.failure-history-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.failure-history-item {
padding: 0.75rem;
background: hsl(var(--destructive) / 0.06);
border: 1px solid hsl(var(--destructive) / 0.15);
border-radius: 0.5rem;
}
.failure-history-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
color: hsl(var(--destructive));
}
.failure-history-count {
font-size: 0.875rem;
font-weight: 500;
}
.failure-history-timestamp {
margin-left: auto;
}
.failure-history-content {
display: flex;
flex-direction: column;
gap: 0.375rem;
padding-left: 0.5rem;
}
.failure-history-task,
.failure-history-error {
display: flex;
align-items: center;
gap: 0.375rem;
}
.failure-history-message pre {
margin: 0;
white-space: pre-wrap;
}
.failure-history-stacktrace {
margin-top: 0.375rem;
}
.failure-history-stacktrace summary {
margin-bottom: 0.25rem;
}
.failure-history-stacktrace pre {
margin: 0;
background: hsl(var(--background));
padding: 0.5rem;
border-radius: 0.25rem;
border: 1px solid hsl(var(--border));
}
.detail-label-sm {
font-size: 0.75rem;
font-weight: 500;
color: hsl(var(--muted-foreground));
min-width: 60px;
}
/* Priority Badges */
.issue-priority {
display: inline-flex;

View File

@@ -431,8 +431,6 @@ function renderIssueCard(issue) {
<span>Archived on ${archivedDate}</span>
</div>
` : ''}
${renderFailureInfo(issue)}
</div>
`;
}
@@ -479,6 +477,72 @@ function renderFailureInfo(issue) {
`;
}
function renderFailureHistoryDetail(issue) {
// Check if issue has failure feedback
if (!issue.feedback || issue.feedback.length === 0) {
return '';
}
// Extract failure feedbacks
const failures = issue.feedback.filter(f => f.type === 'failure' && f.stage === 'execute');
if (failures.length === 0) {
return '';
}
return `
<div class="detail-section">
<label class="detail-label">${t('issues.failureHistory') || 'Failure History'} (${failures.length})</label>
<div class="failure-history-list">
${failures.map((failure, index) => {
let failureDetail;
try {
failureDetail = JSON.parse(failure.content);
} catch {
return '';
}
const errorMessage = failureDetail.message || 'Unknown error';
const errorType = failureDetail.error_type || 'error';
const taskId = failureDetail.task_id;
const timestamp = failure.created_at ? new Date(failure.created_at).toLocaleString() : 'Unknown time';
return `
<div class="failure-history-item">
<div class="failure-history-header">
<i data-lucide="alert-circle" class="w-4 h-4"></i>
<span class="failure-history-count">Failure ${index + 1}</span>
<span class="failure-history-timestamp text-xs text-muted-foreground">${timestamp}</span>
</div>
<div class="failure-history-content">
${taskId ? `
<div class="failure-history-task">
<span class="detail-label-sm">Task:</span>
<span class="font-mono text-xs">${taskId}</span>
</div>
` : ''}
<div class="failure-history-error">
<span class="detail-label-sm">Error Type:</span>
<span class="font-mono text-xs">${errorType}</span>
</div>
<div class="failure-history-message">
<span class="detail-label-sm">Message:</span>
<pre class="detail-pre text-xs">${escapeHtml(errorMessage)}</pre>
</div>
${failureDetail.stack_trace ? `
<details class="failure-history-stacktrace">
<summary class="cursor-pointer text-xs text-muted-foreground">Show Stack Trace</summary>
<pre class="detail-pre text-xs mt-1 max-h-60 overflow-auto">${escapeHtml(failureDetail.stack_trace)}</pre>
</details>
` : ''}
</div>
</div>
`;
}).join('')}
</div>
</div>
`;
}
// Helper: Truncate text to max length
function truncateText(text, maxLength) {
if (!text || text.length <= maxLength) return text;
@@ -1691,6 +1755,9 @@ function renderIssueDetailPanel(issue) {
</div>
</div>
<!-- Failure History -->
${renderFailureHistoryDetail(issue)}
<!-- Solutions -->
<div class="detail-section">
<label class="detail-label">${t('issues.solutions') || 'Solutions'} (${issue.solutions?.length || 0})</label>