mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-09-24 18:30:49 +02:00
Add files via upload
This commit is contained in:
@@ -2580,6 +2580,8 @@
|
|||||||
"agentModeSingle": "Single-agent (Eino ADK)",
|
"agentModeSingle": "Single-agent (Eino ADK)",
|
||||||
"agentModeMulti": "Multi-agent (Eino)",
|
"agentModeMulti": "Multi-agent (Eino)",
|
||||||
"agentModeHint": "Same as chat: Eino single-agent (ADK), or Deep / Plan-Execute / Supervisor (last three require multi_agent.enabled).",
|
"agentModeHint": "Same as chat: Eino single-agent (ADK), or Deep / Plan-Execute / Supervisor (last three require multi_agent.enabled).",
|
||||||
|
"concurrency": "Concurrency",
|
||||||
|
"concurrencyHint": "Number of subtasks to run in parallel (1-8). Default 1 is serial; use 1-2 for scan-heavy tasks.",
|
||||||
"scheduleMode": "Schedule mode",
|
"scheduleMode": "Schedule mode",
|
||||||
"scheduleModeManual": "Manual",
|
"scheduleModeManual": "Manual",
|
||||||
"scheduleModeCron": "Cron expression",
|
"scheduleModeCron": "Cron expression",
|
||||||
@@ -2594,8 +2596,8 @@
|
|||||||
"tasksList": "Task list (one task per line)",
|
"tasksList": "Task list (one task per line)",
|
||||||
"tasksListPlaceholder": "Enter task list, one per line",
|
"tasksListPlaceholder": "Enter task list, one per line",
|
||||||
"tasksListPlaceholderExample": "Enter task list, one per line, for example:\nScan open ports of 192.168.1.1\nCheck if https://example.com has SQL injection\nEnumerate subdomains of example.com",
|
"tasksListPlaceholderExample": "Enter task list, one per line, for example:\nScan open ports of 192.168.1.1\nCheck if https://example.com has SQL injection\nEnumerate subdomains of example.com",
|
||||||
"tasksListHint": "Enter one task command per line; the system will execute them in order. Empty lines are ignored.",
|
"tasksListHint": "Enter one task command per line; the system runs them via a concurrency pool. Empty lines are ignored.",
|
||||||
"tasksListHintFull": "Hint: Enter one task command per line; the system will execute these tasks in order. Empty lines are ignored.",
|
"tasksListHintFull": "Hint: Enter one task command per line; the system runs them via a concurrency pool. Empty lines are ignored.",
|
||||||
"createQueue": "Create queue"
|
"createQueue": "Create queue"
|
||||||
},
|
},
|
||||||
"batchQueueDetailModal": {
|
"batchQueueDetailModal": {
|
||||||
@@ -2629,6 +2631,8 @@
|
|||||||
"scheduleToggleFailed": "Failed to update schedule toggle",
|
"scheduleToggleFailed": "Failed to update schedule toggle",
|
||||||
"completedAt": "Completed at",
|
"completedAt": "Completed at",
|
||||||
"taskTotal": "Total tasks",
|
"taskTotal": "Total tasks",
|
||||||
|
"concurrency": "Concurrency",
|
||||||
|
"concurrencyEditHint": "Click to edit. Cannot change while the queue is running.",
|
||||||
"taskList": "Task list",
|
"taskList": "Task list",
|
||||||
"startLabel": "Start",
|
"startLabel": "Start",
|
||||||
"completeLabel": "Complete",
|
"completeLabel": "Complete",
|
||||||
|
|||||||
@@ -2568,6 +2568,8 @@
|
|||||||
"agentModeSingle": "单代理(Eino ADK)",
|
"agentModeSingle": "单代理(Eino ADK)",
|
||||||
"agentModeMulti": "多代理(Eino)",
|
"agentModeMulti": "多代理(Eino)",
|
||||||
"agentModeHint": "与对话页一致:Eino 单代理(ADK),或 Deep / Plan-Execute / Supervisor(后三种需已启用多代理)。",
|
"agentModeHint": "与对话页一致:Eino 单代理(ADK),或 Deep / Plan-Execute / Supervisor(后三种需已启用多代理)。",
|
||||||
|
"concurrency": "并发数",
|
||||||
|
"concurrencyHint": "同时执行的子任务数量(1-8)。默认 1 为串行;含扫描类工具时建议 1-2。",
|
||||||
"scheduleMode": "调度方式",
|
"scheduleMode": "调度方式",
|
||||||
"scheduleModeManual": "手工执行",
|
"scheduleModeManual": "手工执行",
|
||||||
"scheduleModeCron": "调度表达式(Cron)",
|
"scheduleModeCron": "调度表达式(Cron)",
|
||||||
@@ -2582,8 +2584,8 @@
|
|||||||
"tasksList": "任务列表(每行一个任务)",
|
"tasksList": "任务列表(每行一个任务)",
|
||||||
"tasksListPlaceholder": "请输入任务列表,每行一个任务",
|
"tasksListPlaceholder": "请输入任务列表,每行一个任务",
|
||||||
"tasksListPlaceholderExample": "请输入任务列表,每行一个任务,例如:\n扫描 192.168.1.1 的开放端口\n检查 https://example.com 是否存在SQL注入\n枚举 example.com 的子域名",
|
"tasksListPlaceholderExample": "请输入任务列表,每行一个任务,例如:\n扫描 192.168.1.1 的开放端口\n检查 https://example.com 是否存在SQL注入\n枚举 example.com 的子域名",
|
||||||
"tasksListHint": "每行输入一个任务指令,系统将依次执行这些任务。空行会被自动忽略。",
|
"tasksListHint": "每行输入一个任务指令,系统将按并发池执行这些任务。空行会被自动忽略。",
|
||||||
"tasksListHintFull": "提示:每行输入一个任务指令,系统将依次执行这些任务。空行会被自动忽略。",
|
"tasksListHintFull": "提示:每行输入一个任务指令,系统将按并发池执行这些任务。空行会被自动忽略。",
|
||||||
"createQueue": "创建队列"
|
"createQueue": "创建队列"
|
||||||
},
|
},
|
||||||
"batchQueueDetailModal": {
|
"batchQueueDetailModal": {
|
||||||
@@ -2617,6 +2619,8 @@
|
|||||||
"scheduleToggleFailed": "更新调度开关失败",
|
"scheduleToggleFailed": "更新调度开关失败",
|
||||||
"completedAt": "完成时间",
|
"completedAt": "完成时间",
|
||||||
"taskTotal": "任务总数",
|
"taskTotal": "任务总数",
|
||||||
|
"concurrency": "并发数",
|
||||||
|
"concurrencyEditHint": "点击可修改;队列运行中不可改。",
|
||||||
"taskList": "任务列表",
|
"taskList": "任务列表",
|
||||||
"startLabel": "开始",
|
"startLabel": "开始",
|
||||||
"completeLabel": "完成",
|
"completeLabel": "完成",
|
||||||
|
|||||||
@@ -990,6 +990,7 @@ async function createBatchQueue() {
|
|||||||
const roleSelect = document.getElementById('batch-queue-role');
|
const roleSelect = document.getElementById('batch-queue-role');
|
||||||
const projectSelect = document.getElementById('batch-queue-project-id');
|
const projectSelect = document.getElementById('batch-queue-project-id');
|
||||||
const agentModeSelect = document.getElementById('batch-queue-agent-mode');
|
const agentModeSelect = document.getElementById('batch-queue-agent-mode');
|
||||||
|
const concurrencyInput = document.getElementById('batch-queue-concurrency');
|
||||||
const scheduleModeSelect = document.getElementById('batch-queue-schedule-mode');
|
const scheduleModeSelect = document.getElementById('batch-queue-schedule-mode');
|
||||||
const cronExprInput = document.getElementById('batch-queue-cron-expr');
|
const cronExprInput = document.getElementById('batch-queue-cron-expr');
|
||||||
const executeNowCheckbox = document.getElementById('batch-queue-execute-now');
|
const executeNowCheckbox = document.getElementById('batch-queue-execute-now');
|
||||||
@@ -1019,6 +1020,9 @@ async function createBatchQueue() {
|
|||||||
const scheduleMode = scheduleModeSelect ? (scheduleModeSelect.value === 'cron' ? 'cron' : 'manual') : 'manual';
|
const scheduleMode = scheduleModeSelect ? (scheduleModeSelect.value === 'cron' ? 'cron' : 'manual') : 'manual';
|
||||||
const cronExpr = cronExprInput ? cronExprInput.value.trim() : '';
|
const cronExpr = cronExprInput ? cronExprInput.value.trim() : '';
|
||||||
const executeNow = executeNowCheckbox ? !!executeNowCheckbox.checked : false;
|
const executeNow = executeNowCheckbox ? !!executeNowCheckbox.checked : false;
|
||||||
|
let concurrency = concurrencyInput ? parseInt(concurrencyInput.value, 10) : 1;
|
||||||
|
if (!Number.isFinite(concurrency) || concurrency < 1) concurrency = 1;
|
||||||
|
if (concurrency > 8) concurrency = 8;
|
||||||
if (scheduleMode === 'cron' && !cronExpr) {
|
if (scheduleMode === 'cron' && !cronExpr) {
|
||||||
alert(_t('batchImportModal.cronExprRequired'));
|
alert(_t('batchImportModal.cronExprRequired'));
|
||||||
return;
|
return;
|
||||||
@@ -1043,6 +1047,7 @@ async function createBatchQueue() {
|
|||||||
cronExpr,
|
cronExpr,
|
||||||
executeNow,
|
executeNow,
|
||||||
projectId,
|
projectId,
|
||||||
|
concurrency,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1489,6 +1494,7 @@ async function showBatchQueueDetail(queueId) {
|
|||||||
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.role'))}</span><span class="bq-kv__v" id="bq-role-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditRole()" title="${escapeHtml(_t('common.edit'))}">${roleLineVal}</span>` : roleLineVal}</span></div>
|
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.role'))}</span><span class="bq-kv__v" id="bq-role-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditRole()" title="${escapeHtml(_t('common.edit'))}">${roleLineVal}</span>` : roleLineVal}</span></div>
|
||||||
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchImportModal.agentMode'))}</span><span class="bq-kv__v" id="bq-agentmode-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditAgentMode()" title="${escapeHtml(_t('common.edit'))}">${escapeHtml(agentModeText)}</span>` : escapeHtml(agentModeText)}</span></div>
|
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchImportModal.agentMode'))}</span><span class="bq-kv__v" id="bq-agentmode-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditAgentMode()" title="${escapeHtml(_t('common.edit'))}">${escapeHtml(agentModeText)}</span>` : escapeHtml(agentModeText)}</span></div>
|
||||||
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchImportModal.scheduleMode'))}</span><span class="bq-kv__v" id="bq-schedule-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditSchedule()" title="${escapeHtml(_t('common.edit'))}">${scheduleDetail}</span>` : scheduleDetail}</span></div>
|
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchImportModal.scheduleMode'))}</span><span class="bq-kv__v" id="bq-schedule-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditSchedule()" title="${escapeHtml(_t('common.edit'))}">${scheduleDetail}</span>` : scheduleDetail}</span></div>
|
||||||
|
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.concurrency'))}</span><span class="bq-kv__v" id="bq-concurrency-val">${allowSubtaskMutation ? `<span class="bq-inline-editable" onclick="startInlineEditConcurrency()" title="${escapeHtml(_t('common.edit'))}">${escapeHtml(String(queue.concurrency && queue.concurrency > 0 ? queue.concurrency : 1))}</span>` : escapeHtml(String(queue.concurrency && queue.concurrency > 0 ? queue.concurrency : 1))}</span></div>
|
||||||
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.taskTotal'))}</span><span class="bq-kv__v">${queue.tasks.length}</span></div>
|
<div class="bq-kv"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.taskTotal'))}</span><span class="bq-kv__v">${queue.tasks.length}</span></div>
|
||||||
${queue.scheduleMode === 'cron' ? `<div class="bq-kv bq-kv--block"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.scheduleCronAuto'))}</span><span class="bq-kv__v bq-kv__v--control"><label class="bq-cron-toggle"><input type="checkbox" ${queue.scheduleEnabled !== false ? 'checked' : ''} onchange="updateBatchQueueScheduleEnabled(this.checked)" /><span class="bq-cron-toggle__hint">${escapeHtml(_t('batchQueueDetailModal.scheduleCronAutoHint'))}</span></label></span></div>` : ''}
|
${queue.scheduleMode === 'cron' ? `<div class="bq-kv bq-kv--block"><span class="bq-kv__k">${escapeHtml(_t('batchQueueDetailModal.scheduleCronAuto'))}</span><span class="bq-kv__v bq-kv__v--control"><label class="bq-cron-toggle"><input type="checkbox" ${queue.scheduleEnabled !== false ? 'checked' : ''} onchange="updateBatchQueueScheduleEnabled(this.checked)" /><span class="bq-cron-toggle__hint">${escapeHtml(_t('batchQueueDetailModal.scheduleCronAutoHint'))}</span></label></span></div>` : ''}
|
||||||
</section>
|
</section>
|
||||||
@@ -2287,6 +2293,75 @@ async function saveInlineAgentMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeBatchQueueConcurrencyInput(raw) {
|
||||||
|
let n = parseInt(raw, 10);
|
||||||
|
if (!Number.isFinite(n) || n < 1) n = 1;
|
||||||
|
if (n > 8) n = 8;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 内联编辑:并发数 ---
|
||||||
|
function startInlineEditConcurrency() {
|
||||||
|
const container = document.getElementById('bq-concurrency-val');
|
||||||
|
if (!container) return;
|
||||||
|
const queueId = batchQueuesState.currentQueueId;
|
||||||
|
if (!queueId) return;
|
||||||
|
apiFetch(`/api/batch-tasks/${queueId}`).then(r => r.json()).then(detail => {
|
||||||
|
const queue = detail.queue || {};
|
||||||
|
const current = normalizeBatchQueueConcurrencyInput(queue.concurrency || 1);
|
||||||
|
container.innerHTML = `<span class="bq-inline-edit-controls">
|
||||||
|
<input type="number" id="bq-edit-concurrency" min="1" max="8" value="${current}" style="width:72px;" />
|
||||||
|
</span>`;
|
||||||
|
const inp = document.getElementById('bq-edit-concurrency');
|
||||||
|
if (!inp) return;
|
||||||
|
inp.focus();
|
||||||
|
inp.select();
|
||||||
|
let cancelled = false;
|
||||||
|
inp.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'Enter') { e.preventDefault(); inp.blur(); }
|
||||||
|
if (e.key === 'Escape') { cancelled = true; cancelAllInlineEdits(); }
|
||||||
|
});
|
||||||
|
inp.addEventListener('blur', () => {
|
||||||
|
if (!cancelled) saveInlineConcurrency();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveInlineConcurrency() {
|
||||||
|
if (_bqInlineSaving) return;
|
||||||
|
_bqInlineSaving = true;
|
||||||
|
const queueId = batchQueuesState.currentQueueId;
|
||||||
|
if (!queueId) { _bqInlineSaving = false; return; }
|
||||||
|
const inp = document.getElementById('bq-edit-concurrency');
|
||||||
|
const concurrency = normalizeBatchQueueConcurrencyInput(inp ? inp.value : 1);
|
||||||
|
try {
|
||||||
|
const detailResp = await apiFetch(`/api/batch-tasks/${queueId}`);
|
||||||
|
const detail = await detailResp.json();
|
||||||
|
const q = detail.queue || {};
|
||||||
|
const response = await apiFetch(`/api/batch-tasks/${queueId}/metadata`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
title: q.title || '',
|
||||||
|
role: q.role || '',
|
||||||
|
agentMode: q.agentMode || 'eino_single',
|
||||||
|
concurrency,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
const result = await response.json().catch(() => ({}));
|
||||||
|
throw new Error(result.error || _t('tasks.updateTaskFailed'));
|
||||||
|
}
|
||||||
|
_bqInlineSaving = false;
|
||||||
|
showBatchQueueDetail(queueId);
|
||||||
|
refreshBatchQueues();
|
||||||
|
} catch (e) {
|
||||||
|
_bqInlineSaving = false;
|
||||||
|
console.error(e);
|
||||||
|
alert(e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- 单条执行 ---
|
// --- 单条执行 ---
|
||||||
async function runSingleBatchTask(queueId, taskId) {
|
async function runSingleBatchTask(queueId, taskId) {
|
||||||
if (!queueId || !taskId) return;
|
if (!queueId || !taskId) return;
|
||||||
@@ -2441,6 +2516,8 @@ window.startInlineEditRole = startInlineEditRole;
|
|||||||
window.saveInlineRole = saveInlineRole;
|
window.saveInlineRole = saveInlineRole;
|
||||||
window.startInlineEditAgentMode = startInlineEditAgentMode;
|
window.startInlineEditAgentMode = startInlineEditAgentMode;
|
||||||
window.saveInlineAgentMode = saveInlineAgentMode;
|
window.saveInlineAgentMode = saveInlineAgentMode;
|
||||||
|
window.startInlineEditConcurrency = startInlineEditConcurrency;
|
||||||
|
window.saveInlineConcurrency = saveInlineConcurrency;
|
||||||
window.runSingleBatchTask = runSingleBatchTask;
|
window.runSingleBatchTask = runSingleBatchTask;
|
||||||
window.startInlineEditSchedule = startInlineEditSchedule;
|
window.startInlineEditSchedule = startInlineEditSchedule;
|
||||||
window.toggleInlineScheduleCron = toggleInlineScheduleCron;
|
window.toggleInlineScheduleCron = toggleInlineScheduleCron;
|
||||||
|
|||||||
@@ -4010,6 +4010,11 @@
|
|||||||
</select>
|
</select>
|
||||||
<div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.agentModeHint">与对话页一致:Eino 单代理(ADK),或 Deep / Plan-Execute / Supervisor(后三种需已启用多代理)。</div>
|
<div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.agentModeHint">与对话页一致:Eino 单代理(ADK),或 Deep / Plan-Execute / Supervisor(后三种需已启用多代理)。</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="batch-queue-concurrency" data-i18n="batchImportModal.concurrency">并发数</label>
|
||||||
|
<input type="number" id="batch-queue-concurrency" min="1" max="8" value="1" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 0.875rem;" />
|
||||||
|
<div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.concurrencyHint">同时执行的子任务数量(1-8)。默认 1 为串行;含扫描类工具时建议 1-2。</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="batch-queue-schedule-mode" data-i18n="batchImportModal.scheduleMode">调度方式</label>
|
<label for="batch-queue-schedule-mode" data-i18n="batchImportModal.scheduleMode">调度方式</label>
|
||||||
<select id="batch-queue-schedule-mode" onchange="handleBatchScheduleModeChange()" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 0.875rem;">
|
<select id="batch-queue-schedule-mode" onchange="handleBatchScheduleModeChange()" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 0.875rem;">
|
||||||
|
|||||||
Reference in New Issue
Block a user