mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-14 15:10:20 +02:00
Add files via upload
This commit is contained in:
@@ -396,7 +396,7 @@
|
|||||||
"stopTask": "Stop task",
|
"stopTask": "Stop task",
|
||||||
"interruptModalTitle": "Interrupt current step",
|
"interruptModalTitle": "Interrupt current step",
|
||||||
"interruptReasonLabel": "Interrupt note",
|
"interruptReasonLabel": "Interrupt note",
|
||||||
"interruptModalHint": "Your note is saved as a user message and the agent continues in the same stream. Use \"Stop completely\" to end the task.",
|
"interruptModalHint": "Same as MCP monitor \"Stop tool\": ends only the in-flight tool call; the conversation and this run continue. Optional note is merged into the tool result (bilingual USER INTERRUPT NOTE, not raw CLI). Leave empty for a plain stop. If no tool is running yet (model still thinking), wait for a tool call or use \"Stop completely\".",
|
||||||
"interruptReasonPlaceholder": "e.g. Tool is too slow—skip and summarize…",
|
"interruptReasonPlaceholder": "e.g. Tool is too slow—skip and summarize…",
|
||||||
"interruptReasonRequired": "Please enter a short note so the model can continue accordingly.",
|
"interruptReasonRequired": "Please enter a short note so the model can continue accordingly.",
|
||||||
"interruptSubmitting": "Submitting...",
|
"interruptSubmitting": "Submitting...",
|
||||||
|
|||||||
@@ -385,7 +385,7 @@
|
|||||||
"stopTask": "停止任务",
|
"stopTask": "停止任务",
|
||||||
"interruptModalTitle": "中断当前步骤",
|
"interruptModalTitle": "中断当前步骤",
|
||||||
"interruptReasonLabel": "中断说明",
|
"interruptReasonLabel": "中断说明",
|
||||||
"interruptModalHint": "填写说明后将作为一条用户消息写入对话,智能体在同一会话内继续迭代。若只需完全停止任务,请点「彻底停止」。",
|
"interruptModalHint": "与 MCP 监控页「终止工具」一致:仅结束当前这一次工具调用,整条对话与本轮推理会继续;工具返回中可附带说明(中英 USER INTERRUPT NOTE 块,与命令行原文区分)。留空则等同仅终止工具。若当前没有工具在执行(模型尚在思考),请等待工具开始或改用「彻底停止」。",
|
||||||
"interruptReasonPlaceholder": "例如:工具耗时过长,请先跳过并总结当前结果…",
|
"interruptReasonPlaceholder": "例如:工具耗时过长,请先跳过并总结当前结果…",
|
||||||
"interruptReasonRequired": "请填写中断说明,以便模型根据你的意图继续。",
|
"interruptReasonRequired": "请填写中断说明,以便模型根据你的意图继续。",
|
||||||
"interruptSubmitting": "提交中...",
|
"interruptSubmitting": "提交中...",
|
||||||
|
|||||||
+44
-36
@@ -356,6 +356,23 @@ function isChatMessagesPinnedToBottom() {
|
|||||||
return scrollHeight - clientHeight - scrollTop <= CHAT_SCROLL_PIN_THRESHOLD_PX;
|
return scrollHeight - clientHeight - scrollTop <= CHAT_SCROLL_PIN_THRESHOLD_PX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 顶栏「停止任务」与进度条按钮对齐时,用会话 ID 反查当前页的 progress 块 ID(无则弹窗内仍可按会话取消) */
|
||||||
|
function findProgressIdByConversationId(conversationId) {
|
||||||
|
if (!conversationId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let fallback = null;
|
||||||
|
for (const [pid, st] of progressTaskState) {
|
||||||
|
if (st && st.conversationId === conversationId) {
|
||||||
|
fallback = pid;
|
||||||
|
if (document.getElementById(pid)) {
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
function registerProgressTask(progressId, conversationId = null) {
|
function registerProgressTask(progressId, conversationId = null) {
|
||||||
const state = progressTaskState.get(progressId) || {};
|
const state = progressTaskState.get(progressId) || {};
|
||||||
state.conversationId = conversationId !== undefined && conversationId !== null
|
state.conversationId = conversationId !== undefined && conversationId !== null
|
||||||
@@ -412,7 +429,7 @@ async function requestCancel(conversationId) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 用户填写说明后中断当前步骤,由后端写入对话并继续同一条流式迭代 */
|
/** 与 MCP 监控一致:仅终止当前进行中的工具调用,工具返回后本轮推理继续(可选 reason 合并进工具结果) */
|
||||||
async function requestCancelWithContinue(conversationId, reason) {
|
async function requestCancelWithContinue(conversationId, reason) {
|
||||||
const response = await apiFetch('/api/agent-loop/cancel', {
|
const response = await apiFetch('/api/agent-loop/cancel', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -433,7 +450,10 @@ async function requestCancelWithContinue(conversationId, reason) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openUserInterruptModal(progressId, conversationId) {
|
function openUserInterruptModal(progressId, conversationId) {
|
||||||
userInterruptModalPending = { progressId, conversationId };
|
userInterruptModalPending = {
|
||||||
|
progressId: progressId != null && progressId !== '' ? progressId : null,
|
||||||
|
conversationId,
|
||||||
|
};
|
||||||
const ta = document.getElementById('user-interrupt-reason');
|
const ta = document.getElementById('user-interrupt-reason');
|
||||||
if (ta) {
|
if (ta) {
|
||||||
ta.value = '';
|
ta.value = '';
|
||||||
@@ -457,13 +477,9 @@ async function submitUserInterruptContinue() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const reason = (document.getElementById('user-interrupt-reason') && document.getElementById('user-interrupt-reason').value || '').trim();
|
const reason = (document.getElementById('user-interrupt-reason') && document.getElementById('user-interrupt-reason').value || '').trim();
|
||||||
if (!reason) {
|
|
||||||
alert(typeof window.t === 'function' ? window.t('tasks.interruptReasonRequired') : '请填写中断说明');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { progressId, conversationId } = userInterruptModalPending;
|
const { progressId, conversationId } = userInterruptModalPending;
|
||||||
closeUserInterruptModal();
|
closeUserInterruptModal();
|
||||||
const stopBtn = document.getElementById(`${progressId}-stop-btn`);
|
const stopBtn = progressId ? document.getElementById(`${progressId}-stop-btn`) : null;
|
||||||
try {
|
try {
|
||||||
if (stopBtn) {
|
if (stopBtn) {
|
||||||
stopBtn.disabled = true;
|
stopBtn.disabled = true;
|
||||||
@@ -486,9 +502,22 @@ async function submitUserInterruptHardCancel() {
|
|||||||
if (!userInterruptModalPending) {
|
if (!userInterruptModalPending) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { progressId } = userInterruptModalPending;
|
const { progressId, conversationId } = userInterruptModalPending;
|
||||||
closeUserInterruptModal();
|
closeUserInterruptModal();
|
||||||
await performHardCancelProgressTask(progressId);
|
if (progressId) {
|
||||||
|
await performHardCancelProgressTask(progressId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!conversationId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await requestCancel(conversationId);
|
||||||
|
loadActiveTasks();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('取消任务失败:', error);
|
||||||
|
alert((typeof window.t === 'function' ? window.t('tasks.cancelTaskFailed') : '取消任务失败') + ': ' + error.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 彻底停止任务(原「停止任务」行为) */
|
/** 彻底停止任务(原「停止任务」行为) */
|
||||||
@@ -1518,18 +1547,6 @@ function handleStreamEvent(event, progressElement, progressId,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'user_interrupt_continue': {
|
|
||||||
const d = event.data || {};
|
|
||||||
const reason = (d.reason != null && String(d.reason).trim() !== '') ? String(d.reason).trim() : (event.message || '');
|
|
||||||
const timelineTitle = typeof window.t === 'function' ? window.t('tasks.userInterruptTimelineTitle') : '用户中断说明(继续迭代)';
|
|
||||||
addTimelineItem(timeline, 'user_interrupt', {
|
|
||||||
title: '✋ ' + timelineTitle,
|
|
||||||
message: reason,
|
|
||||||
data: d,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'progress':
|
case 'progress':
|
||||||
const progressTitle = document.querySelector(`#${progressId} .progress-title`);
|
const progressTitle = document.querySelector(`#${progressId} .progress-title`);
|
||||||
if (progressTitle) {
|
if (progressTitle) {
|
||||||
@@ -2533,7 +2550,7 @@ function renderActiveTasks(tasks) {
|
|||||||
if (cancelBtn) {
|
if (cancelBtn) {
|
||||||
cancelBtn.onclick = (evt) => {
|
cancelBtn.onclick = (evt) => {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
cancelActiveTask(task.conversationId, cancelBtn);
|
cancelActiveTask(task.conversationId);
|
||||||
};
|
};
|
||||||
if (task.status === 'cancelling') {
|
if (task.status === 'cancelling') {
|
||||||
cancelBtn.disabled = true;
|
cancelBtn.disabled = true;
|
||||||
@@ -2546,21 +2563,12 @@ function renderActiveTasks(tasks) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cancelActiveTask(conversationId, button) {
|
function cancelActiveTask(conversationId) {
|
||||||
if (!conversationId) return;
|
if (!conversationId) {
|
||||||
const originalText = button.textContent;
|
return;
|
||||||
button.disabled = true;
|
|
||||||
button.textContent = typeof window.t === 'function' ? window.t('tasks.cancelling') : '取消中...';
|
|
||||||
|
|
||||||
try {
|
|
||||||
await requestCancel(conversationId);
|
|
||||||
loadActiveTasks();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('取消任务失败:', error);
|
|
||||||
alert((typeof window.t === 'function' ? window.t('tasks.cancelTaskFailed') : '取消任务失败') + ': ' + error.message);
|
|
||||||
button.disabled = false;
|
|
||||||
button.textContent = originalText;
|
|
||||||
}
|
}
|
||||||
|
const progressId = findProgressIdByConversationId(conversationId);
|
||||||
|
openUserInterruptModal(progressId, conversationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
let monitorPanelFetchSeq = 0;
|
let monitorPanelFetchSeq = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user