新增: 工具工作流补全(diff_files工具 + 技能清单注入 + 工作流进度共享 + human端到端测试 + 知识库MCP工具)

This commit is contained in:
lxy
2026-08-08 21:24:53 +08:00
parent 6ba6daf188
commit 9eb2995a74
14 changed files with 807 additions and 93 deletions
+2
View File
@@ -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)
+81
View File
@@ -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,
}