mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-18 21:47:17 +02:00
fix: show failed outcomes in finished batch queues
This commit is contained in:
1 parent
91c53ab451
commit
07066f9219
8 files changed
+48
-1
No files matched your search
@@ -108,3 +108,8 @@
|
||||
- Excel 第 47 行:截图显示 NSE 将 `-sT` 当作脚本名,原因是 scan_type 根据“最后一个非标志参数”找插入位置,遇到 additional_args 的 --script 值时插入到了标志与值之间。nmap 的 scan_type 改为置于参数列表开头,保留各 flag/value 相邻关系;其他工具的既有插入规则保留。
|
||||
- `-sC` 与 --script 不是互斥错误;官方说明明确有 --script 时忽略 -sC,故不新增错误拒绝规则。来源:https://nmap.org/book/man-nse.html 。
|
||||
- 读取真实 tools/nmap.yaml 验证截图参数、nse_scripts 字段和尾部 --max-retries 值的完整顺序;既有空可选参数测试通过。测试不向目标发送扫描;本机没有 nmap,因此不声称完成实际扫描验证。
|
||||
|
||||
## 追加:批量队列结果标签
|
||||
|
||||
- Excel 第 58 行:截图的子任务为 failed,队列 completed 表示所有子任务已经结束;绿色“已完成”和 100% 被误认为全部成功。列表和详情共用展示函数,现在全部失败显示失败色及“执行失败”,部分失败显示“已结束(N 项失败)”,详情解释进度统计结束任务,包含失败/取消。后端生命周期和重跑规则不变。
|
||||
- 3 项实际展示函数回归覆盖全失败、混合结果、成功、运行中及已有周期队列的后续运行信息;不扩展调度能力。
|
||||
@@ -60,7 +60,7 @@
|
||||
| 55 | — | - 选择其专用测试会话,打开「终端」。 | 已修复,Unix Shell 回归通过 |
|
||||
| 56 | — | AI看代码给提的问题 | 已修复并有针对性验证 |
|
||||
| 57 | — | 审计日志搜索无结果后,点击“清空”不会清除关键词或恢复列表,无反应 | 当前重置会清空关键词并请求首个无筛选页面,回归未复现 |
|
||||
| 58 | — | 任务失败,也显示已完成 | 待核对 |
|
||||
| 58 | — | 任务失败,也显示已完成 | 已修复队列结果标签:全部失败显示失败,混合结果显示失败数;3 项回归通过 |
|
||||
| 59 | — | 批量任务在“用户并发配额已满”时进入等待调度后,即使后来停止容器、腾出配额,队列仍停在“执行中 | 当前仓库未实现,不扩展能力 |
|
||||
| 60 | — | 资产扫描任务在后续工具调用的 HITL 审批阶段已被系统中断,审批卡片明确显示“任务已中断、审批 | 待核对 |
|
||||
| 61 | — | 问题:事实正文里的 discovered_on: target/xxx 只会当普通文本保存,不会 | 已按建议明确关系字段说明 |
|
||||
|
||||
@@ -46688,3 +46688,9 @@ html[data-theme="dark"] { --tool-blocked-color: #f4bc62; }
|
||||
font-size: .75rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.batch-queue-status-failed {
|
||||
color: var(--error-color, #dc2626);
|
||||
background: rgba(220, 38, 38, 0.08);
|
||||
border-color: rgba(220, 38, 38, 0.25);
|
||||
}
|
||||
@@ -1099,6 +1099,8 @@
|
||||
"toolFailed": "Failed"
|
||||
},
|
||||
"tasks": {
|
||||
"statusEndedWithFailures": "Finished ({{count}} failed)",
|
||||
"finishedProgressHint": "Progress counts finished tasks, including failures and cancellations; it is not the success rate.",
|
||||
"title": "Task Management",
|
||||
"stopTask": "Stop task",
|
||||
"interruptModalTitle": "Interrupt current step",
|
||||
|
||||
@@ -1111,6 +1111,8 @@
|
||||
"toolFailed": "Ошибка"
|
||||
},
|
||||
"tasks": {
|
||||
"statusEndedWithFailures": "Завершено (ошибок: {{count}})",
|
||||
"finishedProgressHint": "Прогресс учитывает завершённые задачи, включая ошибки и отмены, а не долю успешных задач.",
|
||||
"title": "Управление задачами",
|
||||
"stopTask": "Остановить задачу",
|
||||
"interruptModalTitle": "Прервать текущий шаг",
|
||||
|
||||
@@ -1087,6 +1087,8 @@
|
||||
"toolFailed": "失败"
|
||||
},
|
||||
"tasks": {
|
||||
"statusEndedWithFailures": "已结束({{count}} 项失败)",
|
||||
"finishedProgressHint": "进度表示已结束的任务比例,包含失败和取消,不表示成功率。",
|
||||
"title": "任务管理",
|
||||
"stopTask": "停止任务",
|
||||
"interruptModalTitle": "中断当前步骤",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
const fs=require('node:fs'),vm=require('node:vm'),test=require('node:test'),assert=require('node:assert/strict');
|
||||
const source=fs.readFileSync('web/static/js/tasks.js','utf8');
|
||||
const start=source.indexOf('function getBatchQueueStatusPresentation('),end=source.indexOf('\nfunction ',start+10);
|
||||
const c=vm.createContext({_t:key=>key,_tPlain:(key,args)=>key+':'+JSON.stringify(args)});vm.runInContext(source.slice(start,end),c);
|
||||
test('all failed batch tasks show failure even when the queue lifecycle is completed',()=>{
|
||||
const q={status:'completed',tasks:[{status:'failed'},{status:'failed'}]};const p=c.getBatchQueueStatusPresentation(q);
|
||||
assert.equal(p.text,'tasks.statusFailed');assert.equal(p.class,'batch-queue-status-failed');assert.equal(q.status,'completed');
|
||||
});
|
||||
test('mixed outcome names the failure count while successful queues remain completed',()=>{
|
||||
const mixed=c.getBatchQueueStatusPresentation({status:'completed',tasks:[{status:'completed'},{status:'failed'}]});
|
||||
assert.match(mixed.text,/statusEndedWithFailures.*"count":1/);assert.equal(mixed.progressNote,'tasks.finishedProgressHint');
|
||||
assert.equal(c.getBatchQueueStatusPresentation({status:'completed',tasks:[{status:'completed'}]}).text,'tasks.statusCompleted');
|
||||
});
|
||||
test('running queues retain running status and existing recurring queues retain their next-run information',()=>{
|
||||
assert.equal(c.getBatchQueueStatusPresentation({status:'running',tasks:[{status:'failed'}]}).text,'tasks.statusRunning');
|
||||
const p=c.getBatchQueueStatusPresentation({status:'completed',scheduleMode:'cron',scheduleEnabled:true,nextRunAt:'2026-10-07T00:00:00Z',tasks:[{status:'failed'}]});
|
||||
assert.equal(p.text,'tasks.statusFailed');assert.match(p.sublabel,/cronNextRunLine/);assert.equal(p.callout,'tasks.cronRecurringCallout');
|
||||
});
|
||||
@@ -45,6 +45,18 @@ function getBatchQueueStatusPresentation(queue) {
|
||||
const nextStr = queue.nextRunAt ? new Date(queue.nextRunAt).toLocaleString() : '';
|
||||
const empty = { sublabel: null, progressNote: null, callout: null };
|
||||
|
||||
const failedCount = (queue.tasks || []).filter(task => task.status === 'failed').length;
|
||||
if (queue.status === 'completed' && failedCount > 0) {
|
||||
const allFailed = failedCount === (queue.tasks || []).length;
|
||||
return {
|
||||
text: allFailed ? _t('tasks.statusFailed') : _tPlain('tasks.statusEndedWithFailures', { count: failedCount }),
|
||||
class: 'batch-queue-status-failed',
|
||||
sublabel: cronOn && nextStr ? _tPlain('tasks.cronNextRunLine', { time: nextStr }) : null,
|
||||
progressNote: _t('tasks.finishedProgressHint'),
|
||||
callout: cronOn ? _t('tasks.cronRecurringCallout') : null
|
||||
};
|
||||
}
|
||||
|
||||
if (cronOn && queue.status === 'completed') {
|
||||
return {
|
||||
text: _t('tasks.statusCronCycleIdle'),
|
||||
|
||||
Reference in new issue
Block a user