新增: 工具工作流补全(diff_files工具 + 技能清单注入 + 工作流进度共享 + human端到端测试 + 知识库MCP工具)
This commit is contained in:
@@ -168,6 +168,8 @@ function createStore() {
|
||||
startEventListener: workflowStore.startEventListener,
|
||||
stopEventListener: workflowStore.stopEventListener,
|
||||
clearLiveEvents: workflowStore.clearLiveEvents,
|
||||
// B-41: 工作流进度共享推导(按 execId 派生节点状态/进度)
|
||||
workflowProgress: workflowStore.workflowProgress,
|
||||
approveHumanApproval: workflowStore.approveHumanApproval,
|
||||
cancelHumanApproval: workflowStore.cancelHumanApproval,
|
||||
// AR-11(方案A):数据变更联动刷新监听(后端工具执行后 emit df-data-changed)
|
||||
|
||||
@@ -1,7 +1,79 @@
|
||||
import { workflowApi } from '@/api'
|
||||
import { t } from '@/i18n/i18n-helpers'
|
||||
import type { NodeStatus, WorkflowEventPayload } from '@/api/types'
|
||||
import { state, _eventUnlisten, setEventUnlisten } from './state'
|
||||
|
||||
// B-41: 工作流进度共享推导。liveEvents 已全局收集所有 workflow-event,
|
||||
// 此处按 execution_id 重放派生节点状态/进度,供 TaskDetail/ProjectDetail 同源使用,
|
||||
// 替代各自维护一份 onEvent 累加状态(单事实源,并发工作流互不干扰)。
|
||||
export interface WorkflowProgress {
|
||||
nodeStatuses: Record<string, NodeStatus>
|
||||
runningNode: string
|
||||
doneCount: number
|
||||
totalNodes: number
|
||||
result: 'completed' | 'failed' | null
|
||||
}
|
||||
|
||||
function deriveWorkflowProgress(
|
||||
execId: string | null,
|
||||
events: WorkflowEventPayload[],
|
||||
): WorkflowProgress {
|
||||
const empty: WorkflowProgress = {
|
||||
nodeStatuses: {},
|
||||
runningNode: '',
|
||||
doneCount: 0,
|
||||
totalNodes: 0,
|
||||
result: null,
|
||||
}
|
||||
if (!execId) return empty
|
||||
const nodeStatuses: Record<string, NodeStatus> = {}
|
||||
let runningNode = ''
|
||||
let doneCount = 0
|
||||
let totalNodes = 0
|
||||
let result: 'completed' | 'failed' | null = null
|
||||
for (const payload of events) {
|
||||
if (payload.execution_id !== execId) continue
|
||||
const evt = payload.event
|
||||
switch (evt.type) {
|
||||
case 'node_started': {
|
||||
const node = String(evt.node_id ?? '')
|
||||
if (node) {
|
||||
nodeStatuses[node] = 'running'
|
||||
runningNode = node
|
||||
}
|
||||
// 后端模板节点数前端无法预知,用「已启动 + 已完成」近似 total
|
||||
totalNodes = Math.max(totalNodes, doneCount + 1)
|
||||
break
|
||||
}
|
||||
case 'node_completed': {
|
||||
if (runningNode) nodeStatuses[runningNode] = 'completed'
|
||||
runningNode = ''
|
||||
doneCount += 1
|
||||
break
|
||||
}
|
||||
case 'node_failed': {
|
||||
const node = String(evt.node_id ?? '')
|
||||
if (node) nodeStatuses[node] = 'failed'
|
||||
break
|
||||
}
|
||||
case 'node_cancelled': {
|
||||
const node = String(evt.node_id ?? '')
|
||||
if (node) nodeStatuses[node] = 'skipped'
|
||||
break
|
||||
}
|
||||
case 'workflow_completed':
|
||||
result = 'completed'
|
||||
break
|
||||
case 'workflow_failed':
|
||||
result = 'failed'
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
return { nodeStatuses, runningNode, doneCount, totalNodes, result }
|
||||
}
|
||||
|
||||
// B-03b-R10(⑦ 互斥): 审批响应/取消 IPC 进行中标记(模块级单例,createWorkflowStore 每会话只跑一次)。
|
||||
// 防双击/连点在同一轮 IPC 未返回前发起第二次(后端无幂等键,第二次会重复消费 Request 触发
|
||||
// "node already completed" 类报错)。store 层守卫优于按钮 disabled: 共享单例 state,跨调用方统一。
|
||||
@@ -77,6 +149,14 @@ export function createWorkflowStore() {
|
||||
state.liveEvents = []
|
||||
}
|
||||
|
||||
/**
|
||||
* B-41: 按 execution_id 派生工作流进度(读全局 liveEvents,响应式)。
|
||||
* 供 TaskDetail(自身推进的 execId)/ ProjectDetail(最近一次执行)共用同源状态。
|
||||
*/
|
||||
function workflowProgress(execId: string | null): WorkflowProgress {
|
||||
return deriveWorkflowProgress(execId, state.liveEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送审批响应。
|
||||
*
|
||||
@@ -165,6 +245,7 @@ export function createWorkflowStore() {
|
||||
startEventListener,
|
||||
stopEventListener,
|
||||
clearLiveEvents,
|
||||
workflowProgress,
|
||||
approveHumanApproval,
|
||||
cancelHumanApproval,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user