fix(web): 多 task 草稿自动保存后继续推进下一 task

useWorkbenchAiApplicationPreviewFlow 在自动保存草稿分支透传 onApplicationActionCompleted,
确保草稿/提交完成后仍能按 remaining tasks 推进,修复多 task 报销场景后续步骤不启动。
更新 application-context-submit/intent-planner-model 测试,补充 bug 日志与开发日志。
This commit is contained in:
caoxiaozhu
2026-06-29 20:17:36 +08:00
parent 6bdaeed6d4
commit 08f023243e
6 changed files with 120 additions and 6 deletions

View File

@@ -19,7 +19,7 @@ function createInlineMessage(role, content, options = {}) {
}
}
function buildApplicationPreviewFlowHarness(messages) {
function buildApplicationPreviewFlowHarness(messages, options = {}) {
const conversationMessages = createRef(messages)
const applicationSubmitConfirmOpen = createRef(false)
const applicationSubmitConfirmContext = createRef(null)
@@ -69,7 +69,8 @@ function buildApplicationPreviewFlowHarness(messages) {
resolveLatestInlineUserPrompt: () => '2026-02-20 至 2026-02-23去上海出差交通火车保存草稿',
scrollInlineConversationToBottom: () => {},
sending: createRef(false),
toast: () => {}
toast: () => {},
onApplicationActionCompleted: options.onApplicationActionCompleted
})
return {
@@ -80,6 +81,72 @@ function buildApplicationPreviewFlowHarness(messages) {
}
}
test('workbench auto-saved application draft continues remaining steward task', async () => {
const originalFetch = globalThis.fetch
const requests = []
globalThis.fetch = async (url, options = {}) => {
const normalizedUrl = String(url)
if (normalizedUrl.includes('/reimbursements/application-preview-action')) {
const body = JSON.parse(String(options.body || '{}'))
requests.push({ url: normalizedUrl, body })
return {
ok: true,
async json() {
return {
status: 'succeeded',
result: {
draft_payload: {
claim_id: 'claim-auto-saved-draft',
claim_no: 'AEW2DDAFL',
status: 'draft'
}
}
}
}
}
}
throw new Error(`unexpected request: ${normalizedUrl}`)
}
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-25',
reason: '业务招待费报销'
}
}]
const harness = buildApplicationPreviewFlowHarness([], {
onApplicationActionCompleted: (tasks, sourceMessage) => {
continuedTasks.push({ tasks, sourceMessage })
}
})
await harness.flow.startAiApplicationPreview('travel', '差旅费', '2月20-23日去上海出差3天服务国网服务器部署并且报销昨天的业务招待费2000元', {
autoSaveDraft: true,
stewardRemainingTasks: remainingTasks,
onApplicationActionCompleted: (tasks, sourceMessage) => {
continuedTasks.push({ tasks, sourceMessage, fromOptions: true })
}
})
assert.equal(requests.length, 1)
assert.equal(continuedTasks.length, 1)
assert.deepEqual(continuedTasks[0].tasks, remainingTasks)
assert.equal(continuedTasks[0].sourceMessage.stewardRemainingTasks, remainingTasks)
assert.equal(continuedTasks[0].fromOptions, true)
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 = []