feat:执行状态单例状态bug修复
This commit is contained in:
@@ -25,6 +25,7 @@ const isFillingSteps = ref(false)
|
||||
const isStopping = ref(false)
|
||||
const isStopPending = ref(false)
|
||||
const currentStepAbortController = ref<{ cancel: () => void } | null>(null)
|
||||
const currentGenerationId = ref('')
|
||||
|
||||
// 解析URL参数
|
||||
function getUrlParam(param: string): string | null {
|
||||
@@ -135,35 +136,36 @@ function resetTextareaHeight() {
|
||||
|
||||
// 停止填充数据的处理函数
|
||||
async function handleStop() {
|
||||
try {
|
||||
if (websocket.connected) {
|
||||
await websocket.send('stop_generation', {
|
||||
goal: searchValue.value
|
||||
})
|
||||
// 标记正在停止中,按钮显示 loading 状态
|
||||
isStopping.value = true
|
||||
isStopPending.value = true
|
||||
agentsStore.setIsStopping(true)
|
||||
success('提示', '正在停止,请稍候...')
|
||||
} else {
|
||||
warning('警告', 'WebSocket 未连接,无法停止')
|
||||
// 未连接时直接重置状态
|
||||
isFillingSteps.value = false
|
||||
currentStepAbortController.value = null
|
||||
agentsStore.setHasStoppedFilling(true)
|
||||
}
|
||||
} catch (error) {
|
||||
notifyError('错误', '停止生成失败')
|
||||
isFillingSteps.value = false
|
||||
currentStepAbortController.value = null
|
||||
agentsStore.setHasStoppedFilling(true)
|
||||
// 检查是否有正在进行的生成任务
|
||||
if (!isFillingSteps.value) {
|
||||
warning('提示', '没有正在进行的生成任务')
|
||||
return
|
||||
}
|
||||
|
||||
// 先设置停止状态(立即显示"停止中...")
|
||||
agentsStore.setIsStopping(true)
|
||||
isStopping.value = true
|
||||
isStopPending.value = true
|
||||
success('提示', '正在停止,请稍候...')
|
||||
|
||||
// 发送停止请求(不等待响应,后端设置 should_stop = True)
|
||||
if (websocket.connected && currentGenerationId.value) {
|
||||
websocket.send('stop_generation', {
|
||||
generation_id: currentGenerationId.value
|
||||
}).then((result: any) => {
|
||||
console.log('停止生成响应:', result)
|
||||
}).catch((error: any) => {
|
||||
console.log('停止生成请求失败(可能已经停止):', error?.message)
|
||||
})
|
||||
}
|
||||
// 不清空 currentGenerationId,让 fillStepTask 循环检查 isStopping 来停止
|
||||
}
|
||||
|
||||
// 监听后端发送的停止完成事件
|
||||
// 监听后端发送的停止完成事件(备用,如果后端有发送)
|
||||
function onGenerationStopped() {
|
||||
isStopping.value = false
|
||||
isStopPending.value = false
|
||||
currentGenerationId.value = ''
|
||||
success('成功', '已停止生成')
|
||||
}
|
||||
|
||||
@@ -185,16 +187,34 @@ async function handleSearch() {
|
||||
}
|
||||
emit('search-start')
|
||||
|
||||
agentsStore.resetAgent()
|
||||
agentsStore.setAgentRawPlan({ loading: true })
|
||||
// 重置所有状态(处理可能的上一次未完成的停止操作)
|
||||
isStopping.value = false
|
||||
isStopPending.value = false
|
||||
agentsStore.setIsStopping(false)
|
||||
agentsStore.setHasStoppedFilling(false)
|
||||
|
||||
agentsStore.resetAgent()
|
||||
agentsStore.setAgentRawPlan({ loading: true })
|
||||
|
||||
// 重置 generation_id
|
||||
currentGenerationId.value = ''
|
||||
|
||||
// 获取大纲
|
||||
const outlineData = await api.generateBasePlan({
|
||||
const response = await api.generateBasePlan({
|
||||
goal: searchValue.value,
|
||||
inputs: []
|
||||
})
|
||||
|
||||
// WebSocket 返回格式: { data: {...}, generation_id, execution_id }
|
||||
// REST API 返回格式: {...}
|
||||
const outlineData = response.data || response
|
||||
|
||||
// 保存 generation_id
|
||||
if (response && response.generation_id) {
|
||||
currentGenerationId.value = response.generation_id
|
||||
console.log('📋 保存 generation_id:', currentGenerationId.value)
|
||||
}
|
||||
|
||||
// 处理简报数据格式
|
||||
outlineData['Collaboration Process'] = changeBriefs(outlineData['Collaboration Process'])
|
||||
|
||||
@@ -209,44 +229,55 @@ async function handleSearch() {
|
||||
isFillingSteps.value = true
|
||||
const steps = outlineData['Collaboration Process'] || []
|
||||
|
||||
// 保存 generation_id 到本地变量,用于 fillStepTask 调用
|
||||
// 这样即使前端停止时清空了 currentGenerationId,当前的 fillStepTask 仍能正确停止
|
||||
const fillTaskGenerationId = currentGenerationId.value
|
||||
|
||||
// 串行填充所有步骤的详情
|
||||
for (const step of steps) {
|
||||
// 检查是否已停止
|
||||
if (!isFillingSteps.value || agentsStore.isStopping) {
|
||||
break
|
||||
try {
|
||||
for (const step of steps) {
|
||||
// 检查是否已停止
|
||||
if (!isFillingSteps.value || agentsStore.isStopping) {
|
||||
break
|
||||
}
|
||||
|
||||
await withRetry(
|
||||
async () => {
|
||||
const detailedStep = await api.fillStepTask({
|
||||
goal: searchValue.value,
|
||||
stepTask: {
|
||||
StepName: step.StepName,
|
||||
TaskContent: step.TaskContent,
|
||||
InputObject_List: step.InputObject_List,
|
||||
OutputObject: step.OutputObject,
|
||||
},
|
||||
generation_id: fillTaskGenerationId,
|
||||
})
|
||||
updateStepDetail(step.StepName, detailedStep)
|
||||
},
|
||||
{
|
||||
maxRetries: 2, // 减少重试次数,因为是串行填充
|
||||
initialDelayMs: 1000, // 使用较小的延迟
|
||||
shouldRetry: () => isFillingSteps.value && !agentsStore.isStopping, // 可取消的重试
|
||||
},
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
// 重置状态(确保即使出错也会执行)
|
||||
triggerOnFocus.value = true
|
||||
if (isStopPending.value) {
|
||||
isStopping.value = false
|
||||
isStopPending.value = false
|
||||
agentsStore.setIsStopping(false)
|
||||
agentsStore.setHasStoppedFilling(true)
|
||||
}
|
||||
isFillingSteps.value = false
|
||||
currentStepAbortController.value = null
|
||||
// 只有在没有停止请求时才清空 generation_id
|
||||
if (!isStopPending.value) {
|
||||
currentGenerationId.value = ''
|
||||
}
|
||||
|
||||
await withRetry(
|
||||
async () => {
|
||||
const detailedStep = await api.fillStepTask({
|
||||
goal: searchValue.value,
|
||||
stepTask: {
|
||||
StepName: step.StepName,
|
||||
TaskContent: step.TaskContent,
|
||||
InputObject_List: step.InputObject_List,
|
||||
OutputObject: step.OutputObject,
|
||||
},
|
||||
})
|
||||
updateStepDetail(step.StepName, detailedStep)
|
||||
},
|
||||
{
|
||||
maxRetries: 2, // 减少重试次数,因为是串行填充
|
||||
initialDelayMs: 1000, // 使用较小的延迟
|
||||
shouldRetry: () => isFillingSteps.value && !agentsStore.isStopping, // 可取消的重试
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// 重置状态
|
||||
triggerOnFocus.value = true
|
||||
if (isStopPending.value) {
|
||||
isStopping.value = false
|
||||
isStopPending.value = false
|
||||
agentsStore.setIsStopping(false)
|
||||
agentsStore.setHasStoppedFilling(true)
|
||||
}
|
||||
isFillingSteps.value = false
|
||||
currentStepAbortController.value = null
|
||||
}
|
||||
|
||||
//更新单个步骤的详情
|
||||
|
||||
@@ -679,10 +679,13 @@ const submitBranch = async () => {
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
// WebSocket 返回格式: { data: [[action1, action2], [action3, action4]], ... }
|
||||
// REST API 返回格式: [[action1, action2], [action3, action4]]
|
||||
const responseData = response.data || response
|
||||
// 后端返回格式: [[action1, action2], [action3, action4]]
|
||||
// 取第一个分支
|
||||
if (response && response.length > 0) {
|
||||
const firstBranch = response[0]
|
||||
if (responseData && responseData.length > 0) {
|
||||
const firstBranch = responseData[0]
|
||||
|
||||
// 直接遍历 action 数组
|
||||
firstBranch.forEach((action: any) => {
|
||||
@@ -974,10 +977,13 @@ const submitBranch = async () => {
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
// WebSocket 返回格式: { data: [[action1, action2], [action3, action4]], ... }
|
||||
// REST API 返回格式: [[action1, action2], [action3, action4]]
|
||||
const responseData = response.data || response
|
||||
// 后端返回格式: [[action1, action2], [action3, action4]]
|
||||
// 取第一个分支
|
||||
if (response && response.length > 0) {
|
||||
const firstBranch = response[0]
|
||||
if (responseData && responseData.length > 0) {
|
||||
const firstBranch = responseData[0]
|
||||
|
||||
// 直接遍历 action 数组
|
||||
firstBranch.forEach((action: any) => {
|
||||
|
||||
@@ -480,8 +480,14 @@ async function handlePauseResume() {
|
||||
// 正常恢复执行
|
||||
try {
|
||||
if (websocket.connected) {
|
||||
// 检查 execution_id 是否存在
|
||||
if (!currentExecutionId.value) {
|
||||
warning('无法恢复', '执行ID不存在,请等待执行开始')
|
||||
return
|
||||
}
|
||||
|
||||
await websocket.send('resume_execution', {
|
||||
execution_id: currentExecutionId.value || ''
|
||||
execution_id: currentExecutionId.value
|
||||
})
|
||||
|
||||
isPaused.value = false
|
||||
@@ -498,12 +504,19 @@ async function handlePauseResume() {
|
||||
// 暂停执行
|
||||
try {
|
||||
if (websocket.connected) {
|
||||
// 检查 execution_id 是否存在
|
||||
if (!currentExecutionId.value) {
|
||||
warning('无法暂停', '执行ID不存在,请等待执行开始')
|
||||
isPausing.value = false
|
||||
return
|
||||
}
|
||||
|
||||
// 先设置 isPausing,允许接收当前正在执行的动作的结果
|
||||
isPausing.value = true
|
||||
info('暂停中', '正在等待当前动作完成')
|
||||
|
||||
await websocket.send('pause_execution', {
|
||||
execution_id: currentExecutionId.value || ''
|
||||
execution_id: currentExecutionId.value
|
||||
})
|
||||
|
||||
/*不立即设置 isPaused = true
|
||||
@@ -881,11 +894,14 @@ async function restartFromStep(stepIndex: number) {
|
||||
// 清空修改记录
|
||||
agentsStore.clearModifiedSteps()
|
||||
|
||||
// 保存旧的 execution_id 用于停止
|
||||
const oldExecutionId = currentExecutionId.value
|
||||
|
||||
// 停止旧的执行
|
||||
if (websocket.connected && currentExecutionId.value) {
|
||||
if (websocket.connected && oldExecutionId) {
|
||||
try {
|
||||
const stopResponse = await websocket.send('stop_execution', {
|
||||
execution_id: currentExecutionId.value || ''
|
||||
await websocket.send('stop_execution', {
|
||||
execution_id: oldExecutionId
|
||||
})
|
||||
// 等待一下确保后端完全停止
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
@@ -893,6 +909,13 @@ async function restartFromStep(stepIndex: number) {
|
||||
console.warn('⚠️ 停止旧执行失败(可能已经停止):', err)
|
||||
}
|
||||
}
|
||||
|
||||
// 前端生成新的 execution_id(确保前端和后端使用同一个 ID)
|
||||
const generalGoal = agentsStore.agentRawPlan.data?.['General Goal'] || ''
|
||||
const newExecutionId = `${generalGoal.replace(/\s+/g, '_')}_${Date.now()}`
|
||||
currentExecutionId.value = newExecutionId
|
||||
console.log('🔄 [DEBUG] restartFromStep: 生成新的 execution_id =', newExecutionId)
|
||||
|
||||
// 构建截断后的 RehearsalLog
|
||||
const truncatedLog = buildTruncatedRehearsalLog(stepIndex)
|
||||
|
||||
@@ -936,7 +959,7 @@ async function restartFromStep(stepIndex: number) {
|
||||
isStreaming.value = true
|
||||
currentExecutionId.value = executionId
|
||||
},
|
||||
undefined,
|
||||
newExecutionId, // 传入前端生成的 execution_id
|
||||
stepIndex,
|
||||
truncatedLog
|
||||
)
|
||||
@@ -1007,8 +1030,41 @@ async function handleTaskProcess() {
|
||||
}
|
||||
|
||||
// 重置执行结果
|
||||
function handleRefresh() {
|
||||
async function handleRefresh() {
|
||||
// 如果有正在执行的任务,先通知后端停止
|
||||
if (websocket.connected && currentExecutionId.value) {
|
||||
try {
|
||||
await websocket.send('stop_execution', {
|
||||
execution_id: currentExecutionId.value
|
||||
})
|
||||
// 等待一下确保后端完全停止
|
||||
await new Promise(resolve => setTimeout(resolve, 500))
|
||||
} catch (err) {
|
||||
console.warn('⚠️ 停止执行失败(可能已经停止):', err)
|
||||
}
|
||||
}
|
||||
|
||||
// 重置所有状态
|
||||
agentsStore.setExecutePlan([])
|
||||
stepExecutionStatus.value = {}
|
||||
sentStepIds.value.clear()
|
||||
currentExecutionId.value = null
|
||||
isPaused.value = false
|
||||
isStreaming.value = false
|
||||
isPausing.value = false
|
||||
loading.value = false
|
||||
isRestarting.value = false
|
||||
|
||||
// 重置进度通知标题
|
||||
currentProgressTitle.value = '任务执行中'
|
||||
|
||||
// 关闭进度通知
|
||||
if (currentProgressNotificationId.value) {
|
||||
removeNotification(currentProgressNotificationId.value)
|
||||
currentProgressNotificationId.value = null
|
||||
}
|
||||
|
||||
success('已重置', '执行状态已重置')
|
||||
}
|
||||
|
||||
// 添加滚动状态指示器
|
||||
|
||||
@@ -797,13 +797,16 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
goal: generalGoal
|
||||
})
|
||||
|
||||
// WebSocket 返回格式: { data: [[{...}]], ... }
|
||||
// REST API 返回格式: [[{...}]]
|
||||
const responseData = response.data || response
|
||||
// 直接获取协作流程数据
|
||||
if (Array.isArray(response)) {
|
||||
if (Array.isArray(responseData)) {
|
||||
// 可能是二维数组
|
||||
newTasks = (response as any[])[0] || []
|
||||
} else if (response && (response as any)['Collaboration Process']) {
|
||||
newTasks = responseData[0] || []
|
||||
} else if (responseData && responseData['Collaboration Process']) {
|
||||
// 如果返回的是对象,尝试读取 Collaboration Process 字段
|
||||
newTasks = (response as any)['Collaboration Process'] || []
|
||||
newTasks = responseData['Collaboration Process'] || []
|
||||
} else {
|
||||
newTasks = []
|
||||
}
|
||||
@@ -1136,14 +1139,17 @@ const handleAddBranch = async (taskId: string, branchContent: string) => {
|
||||
initialInputs: Array.isArray(initialInput) ? initialInput : [initialInput],
|
||||
goal: generalGoal
|
||||
})
|
||||
// WebSocket 返回格式: { data: [[{...}]], ... }
|
||||
// REST API 返回格式: [[{...}]]
|
||||
const responseData = response.data || response
|
||||
// 直接获取协作流程数据
|
||||
// newTasks = response?.[0] || []
|
||||
if (Array.isArray(response)) {
|
||||
if (Array.isArray(responseData)) {
|
||||
// 可能是二维数组
|
||||
newTasks = (response as any[])[0] || []
|
||||
} else if (response && (response as any)['Collaboration Process']) {
|
||||
newTasks = responseData[0] || []
|
||||
} else if (responseData && responseData['Collaboration Process']) {
|
||||
// 如果返回的是对象,尝试读取 Collaboration Process 字段
|
||||
newTasks = (response as any)['Collaboration Process'] || []
|
||||
newTasks = responseData['Collaboration Process'] || []
|
||||
} else {
|
||||
newTasks = []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user