mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-17 23:22:27 +02:00
feat: manage task process lifetimes and preserve turn history
This commit is contained in:
@@ -1107,6 +1107,9 @@
|
||||
"autoRefresh": "Auto refresh",
|
||||
"historyHint": "Tip: Completed task history available. Check \"Show history\" to view.",
|
||||
"statusRunning": "Running",
|
||||
"statusCleanupUnconfirmed": "Remote cancellation unconfirmed",
|
||||
"statusCleaning": "Cleaning up",
|
||||
"statusCleanupFailed": "Cleanup failed (retrying)",
|
||||
"statusCancelling": "Cancelling",
|
||||
"statusFailed": "Failed",
|
||||
"statusTimeout": "Timeout",
|
||||
|
||||
@@ -1095,6 +1095,9 @@
|
||||
"autoRefresh": "自动刷新",
|
||||
"historyHint": "提示:有已完成的任务历史,请勾选\"显示历史记录\"查看",
|
||||
"statusRunning": "执行中",
|
||||
"statusCleanupUnconfirmed": "远端停止状态待确认",
|
||||
"statusCleaning": "清理中",
|
||||
"statusCleanupFailed": "清理异常(自动重试)",
|
||||
"statusCancelling": "取消中",
|
||||
"statusFailed": "执行失败",
|
||||
"statusTimeout": "执行超时",
|
||||
|
||||
@@ -3,7 +3,7 @@ const progressTaskState = new Map();
|
||||
let userInterruptModalPending = null;
|
||||
let activeTaskInterval = null;
|
||||
const ACTIVE_TASK_REFRESH_INTERVAL = 2000; // 运行态与审批态需要及时自刷新
|
||||
const TASK_FINAL_STATUSES = new Set(['failed', 'timeout', 'cancelled', 'completed']);
|
||||
const TASK_FINAL_STATUSES = new Set(['failed', 'timeout', 'cancelled', 'completed', 'cleanup_unconfirmed']);
|
||||
const hitlInterruptToolItemMap = new Map();
|
||||
let activeTasksLoadPromise = null;
|
||||
let activeTasksVisualSignature = '';
|
||||
@@ -7153,13 +7153,16 @@ function renderActiveTasks(tasks) {
|
||||
const statusMap = {
|
||||
'running': _t('tasks.statusRunning'),
|
||||
'cancelling': _t('tasks.statusCancelling'),
|
||||
'cleaning': _t('tasks.statusCleaning'),
|
||||
'cleanup_failed': _t('tasks.statusCleanupFailed'),
|
||||
'cleanup_unconfirmed': _t('tasks.statusCleanupUnconfirmed'),
|
||||
'failed': _t('tasks.statusFailed'),
|
||||
'timeout': _t('tasks.statusTimeout'),
|
||||
'cancelled': _t('tasks.statusCancelled'),
|
||||
'completed': _t('tasks.statusCompleted')
|
||||
};
|
||||
const statusText = statusMap[task.status] || _t('tasks.statusRunning');
|
||||
const isFinalStatus = ['failed', 'timeout', 'cancelled', 'completed'].includes(task.status);
|
||||
const isFinalStatus = ['failed', 'timeout', 'cancelled', 'completed', 'cleanup_unconfirmed'].includes(task.status);
|
||||
const taskDisplayName = getActiveTaskDisplayName(task);
|
||||
const stopTaskBtnText = _t('tasks.stopTask');
|
||||
|
||||
|
||||
+11
-7
@@ -187,7 +187,7 @@ function updateCompletedTasksHistory(currentTasks) {
|
||||
const exists = tasksState.completedTasksHistory.some(t => t.conversationId === task.conversationId);
|
||||
if (!exists) {
|
||||
// 如果任务状态不是最终状态,标记为completed
|
||||
const finalStatus = ['completed', 'failed', 'timeout', 'cancelled'].includes(task.status)
|
||||
const finalStatus = ['completed', 'failed', 'timeout', 'cancelled', 'cleanup_unconfirmed'].includes(task.status)
|
||||
? task.status
|
||||
: 'completed';
|
||||
|
||||
@@ -309,7 +309,7 @@ function updateTaskStats(tasks) {
|
||||
tasks.forEach(task => {
|
||||
if (task.status === 'running') {
|
||||
stats.running++;
|
||||
} else if (task.status === 'cancelling') {
|
||||
} else if (['cancelling', 'cleaning', 'cleanup_failed'].includes(task.status)) {
|
||||
stats.cancelling++;
|
||||
} else if (task.status === 'completed') {
|
||||
stats.completed++;
|
||||
@@ -364,7 +364,7 @@ function filterAndSortTasks() {
|
||||
if (statusFilter === 'active') {
|
||||
// 仅运行中的任务(不包括历史)
|
||||
filtered = tasksState.allTasks.filter(task =>
|
||||
task.status === 'running' || task.status === 'cancelling'
|
||||
['running', 'cancelling', 'cleaning', 'cleanup_failed'].includes(task.status)
|
||||
);
|
||||
} else if (statusFilter === 'history') {
|
||||
// 仅历史记录
|
||||
@@ -445,7 +445,7 @@ function updateTaskDurations() {
|
||||
const status = item.dataset.status;
|
||||
const durationEl = item.querySelector('.task-duration');
|
||||
|
||||
if (durationEl && startedAt && (status === 'running' || status === 'cancelling')) {
|
||||
if (durationEl && startedAt && (['running', 'cancelling', 'cleaning', 'cleanup_failed'].includes(status))) {
|
||||
durationEl.textContent = calculateDuration(startedAt);
|
||||
}
|
||||
});
|
||||
@@ -470,6 +470,9 @@ function renderTasks(tasks) {
|
||||
// 状态映射
|
||||
const statusMap = {
|
||||
'running': { text: _t('tasks.statusRunning'), class: 'task-status-running' },
|
||||
'cleaning': { text: _t('tasks.statusCleaning'), class: 'task-status-cancelling' },
|
||||
'cleanup_unconfirmed': { text: _t('tasks.statusCleanupUnconfirmed'), class: 'task-status-failed' },
|
||||
'cleanup_failed': { text: _t('tasks.statusCleanupFailed'), class: 'task-status-failed' },
|
||||
'cancelling': { text: _t('tasks.statusCancelling'), class: 'task-status-cancelling' },
|
||||
'failed': { text: _t('tasks.statusFailed'), class: 'task-status-failed' },
|
||||
'timeout': { text: _t('tasks.statusTimeout'), class: 'task-status-timeout' },
|
||||
@@ -530,10 +533,10 @@ function renderTaskItem(task, statusMap, isHistory = false) {
|
||||
: '';
|
||||
|
||||
const status = statusMap[task.status] || { text: task.status, class: 'task-status-unknown' };
|
||||
const isFinalStatus = ['failed', 'timeout', 'cancelled', 'completed'].includes(task.status);
|
||||
const canCancel = !isFinalStatus && task.status !== 'cancelling' && !isHistory;
|
||||
const isFinalStatus = ['failed', 'timeout', 'cancelled', 'completed', 'cleanup_unconfirmed'].includes(task.status);
|
||||
const canCancel = !isFinalStatus && !['cancelling', 'cleaning'].includes(task.status) && !isHistory;
|
||||
const isSelected = tasksState.selectedTasks.has(task.conversationId);
|
||||
const duration = (task.status === 'running' || task.status === 'cancelling')
|
||||
const duration = (['running', 'cancelling', 'cleaning', 'cleanup_failed'].includes(task.status))
|
||||
? calculateDuration(task.startedAt)
|
||||
: '';
|
||||
|
||||
@@ -561,6 +564,7 @@ function renderTaskItem(task, statusMap, isHistory = false) {
|
||||
${task.conversationId ? `<button class="btn-secondary btn-small" onclick="viewConversation(${escapeJsStringAttr(task.conversationId)})">` + _t('tasks.viewConversation') + `</button>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
${task.cleanupError ? `<div class="task-details">${escapeHtml(task.cleanupError)}</div>` : ''}
|
||||
${task.conversationId ? `
|
||||
<div class="task-details">
|
||||
<span class="task-id-label">` + _t('tasks.conversationIdLabel') + `:</span>
|
||||
|
||||
Reference in New Issue
Block a user