fix(web): 多 task 串行推进 task2 不再被预览生成时提前触发
onPreviewReadyForNextTask 在 task1 申请核对表刚生成、用户还没操作时就 提前拉起 task2,与用户后续在 task1 上的保存草稿/提交操作互相打架,导致 task2 完全无反应。移除该提前推进回调,统一由 onApplicationActionCompleted 在 task1 真正完成后再推进 task2。 - useWorkbenchAiApplicationPreviewFlow: 删除预览生成时的提前推进分支 - usePersonalWorkbenchAiMode: startModelPlannedApplicationPreview 不再传 onPreviewReadyForNextTask - useWorkbenchAiActionRouter: 低置信确认按钮分支同步删除该回调 - 新增时序回归测试:预览生成不提前推进、保存草稿后才推进 - 更新两处源码正则断言为 doesNotMatch
This commit is contained in:
@@ -147,6 +147,63 @@ test('workbench auto-saved application draft continues remaining steward task',
|
||||
}
|
||||
})
|
||||
|
||||
test('workbench application preview does not continue next task until draft is saved or submitted', async () => {
|
||||
// 时序回归:task1 申请核对表刚生成、用户还没点保存草稿/提交时,
|
||||
// 不能提前拉起 task2(会导致两条流程消息和状态互相打架,最终 task2 无反应)。
|
||||
// task2 的推进必须等 task1 真正完成(onApplicationActionCompleted)后再触发。
|
||||
const originalFetch = globalThis.fetch
|
||||
globalThis.fetch = async (url) => {
|
||||
if (String(url).includes('/reimbursements/application-preview-action')) {
|
||||
return {
|
||||
ok: true,
|
||||
async json() {
|
||||
return { status: 'succeeded', result: { draft_payload: { claim_id: 'c1', claim_no: 'AEW2', status: 'draft' } } }
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(`unexpected request: ${url}`)
|
||||
}
|
||||
|
||||
try {
|
||||
const continuedTasks = []
|
||||
const remainingTasks = [{
|
||||
task_id: 'task-reimbursement-2',
|
||||
task_type: 'reimbursement',
|
||||
assigned_agent: 'reimbursement_assistant',
|
||||
summary: '报销昨天的业务招待费 2000 元',
|
||||
ontology_fields: { expense_type: 'entertainment', amount: '2000元', time_range: '2026-06-29', reason: '业务招待费报销' }
|
||||
}]
|
||||
const harness = buildApplicationPreviewFlowHarness([], {
|
||||
onApplicationActionCompleted: (tasks) => { continuedTasks.push({ tasks, phase: 'module' }) }
|
||||
})
|
||||
|
||||
// 第一步:生成申请核对表(不传 autoSaveDraft,模拟用户需要手动操作 task1)
|
||||
await harness.flow.startAiApplicationPreview('travel', '差旅费', '2月20-23去上海出差,并且报销昨天招待费2000元', {
|
||||
stewardRemainingTasks: remainingTasks,
|
||||
onApplicationActionCompleted: (tasks) => { continuedTasks.push({ tasks, phase: 'options' }) }
|
||||
})
|
||||
|
||||
// 预览生成后,task2 不应被提前拉起
|
||||
assert.equal(continuedTasks.length, 0, '预览生成时不应触发 task2 推进回调')
|
||||
const previewMessage = harness.conversationMessages.value.find((m) => m.applicationPreview)
|
||||
assert.equal(previewMessage?.stewardRemainingTasks?.length, 1, 'task2 应仍挂在核对表消息上等待用户完成 task1')
|
||||
|
||||
// 第二步:用户手动点击"保存草稿"(走 actionRouter,不传 options.onApplicationActionCompleted),
|
||||
// 此时回落到模块级 onApplicationActionCompleted 触发 task2,这正是真实运行时的续跑路径。
|
||||
await harness.flow.executeInlineApplicationPreviewAction('save_draft', previewMessage, {
|
||||
userText: '保存草稿',
|
||||
draftPayload: null
|
||||
})
|
||||
|
||||
assert.equal(continuedTasks.length, 1, '保存草稿完成后应推进 task2')
|
||||
assert.deepEqual(continuedTasks[0].tasks, remainingTasks)
|
||||
assert.equal(continuedTasks[0].phase, 'module', '手动保存草稿走模块级续跑回调')
|
||||
assert.doesNotMatch(harness.conversationMessages.value.at(-1).content, /继续处理费用报销/, '自动续跑时不展示重复的继续处理按钮')
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch
|
||||
}
|
||||
})
|
||||
|
||||
test('workbench saved application draft can be submitted by contextual text without re-planning', async () => {
|
||||
const originalFetch = globalThis.fetch
|
||||
const requests = []
|
||||
|
||||
Reference in New Issue
Block a user