feat(web): AI 工作台多 task 串行推进与会话适配

- useWorkbenchAiApplicationPreviewFlow/useWorkbenchAiActionRouter/useWorkbenchAiCommandIntents 支持 task1 完成后自动推进 task2,确认按钮直接拉起申请预览,草稿/提交成功后继续推进下一 task
- workbenchAiIntentPlannerModel/workbenchAiMessageModel/workbenchAiCommandIntentModel 适配多 task 意图规划与消息结构
- aiApplicationPreviewActions/aiApplicationPrecheckModel/aiExpenseDraftModel/aiWorkbenchConversationStore 草稿与会话存储适配
- PersonalWorkbenchAiMode 与样式适配,更新 preview-actions/expense-draft/conversation-store/fast-preview/action-router/command-intent/intent-planner 测试
This commit is contained in:
caoxiaozhu
2026-06-26 22:42:23 +08:00
parent 5753899eb3
commit c4b5fcc067
22 changed files with 1171 additions and 144 deletions

View File

@@ -93,6 +93,65 @@ test('workbench steward application confirmation opens inline application previe
assert.equal(preview.fields.transportMode, '')
})
test('workbench low-confidence application confirmation forwards remaining tasks', () => {
let previewCall = null
const remainingTasks = [{
task_id: 'task-reimbursement-2',
task_type: 'reimbursement',
assigned_agent: 'reimbursement_assistant',
ontology_fields: {
expense_type: 'entertainment',
expense_type_label: '业务招待费',
amount: '2000元',
time_range: '2026-06-25',
reason: '业务招待'
}
}]
const router = useWorkbenchAiActionRouter({
aiExpenseDraft: { value: null },
applicationFlow: {
isInlineSuggestedActionDisabled: () => false,
executeInlineApplicationPreviewAction: () => {},
startAiApplicationPreview: (...args) => {
previewCall = args
}
},
assistantDraft: { value: '' },
attachmentFlow: {
confirmAiAttachmentAssociation: () => {}
},
emit: () => {},
expenseFlow: {
linkAiExpenseApplication: () => {},
pushInlineExpenseSceneSelectionPrompt: () => {},
startAiApplicationPreviewFromAction: () => {},
startAiExpenseDraft: () => {}
},
focusAiModeInput: () => {},
hasInlineAttachmentOcrDetails: () => false,
resolveLatestInlineUserPrompt: () => '',
selectedFiles: { value: [] },
startInlineConversation: () => {},
toast: () => {},
toggleInlineAttachmentOcrDetails: () => {}
})
router.handleInlineSuggestedAction({
label: '确认发起出差申请',
action_type: 'ai_application_confirm_intent',
payload: {
sourceText: '2月20-23日去上海出差3天服务国网服务器部署并且报销昨天的业务招待费2000元',
ontologyFields: { location: '上海', reason: '服务国网服务器部署' },
stewardRemainingTasks: remainingTasks
}
})
assert.ok(previewCall, 'startAiApplicationPreview 应被调用')
assert.deepEqual(previewCall[3].stewardRemainingTasks, remainingTasks)
assert.equal(typeof previewCall[3].onPreviewReadyForNextTask, 'function')
assert.equal(typeof previewCall[3].onApplicationActionCompleted, 'function')
})
test('workbench reimbursement skip link action opens new reimbursement flow', () => {
let sceneSelectionPayload = null
let fallbackConversationStarted = false
@@ -389,3 +448,70 @@ test('workbench steward executable submit action runs precheck before submit and
globalThis.fetch = originalFetch
}
})
test('workbench steward continue-next-task reimbursement prefills ontology and forwards remaining tasks', () => {
let expenseDraftCall = null
const router = useWorkbenchAiActionRouter({
aiExpenseDraft: { value: null },
applicationFlow: {
isInlineSuggestedActionDisabled: () => false,
executeInlineApplicationPreviewAction: () => {}
},
assistantDraft: { value: '' },
attachmentFlow: {
confirmAiAttachmentAssociation: () => {}
},
emit: () => {},
expenseFlow: {
linkAiExpenseApplication: () => {},
promptAiReimbursementDraftContinuation: () => {},
promptStandaloneReimbursementDraftCreation: () => {},
pushInlineExpenseSceneSelectionPrompt: () => {},
startAiApplicationPreviewFromAction: () => {},
startAiExpenseDraft: (expenseType, expenseTypeLabel, requiresApplicationBeforeReimbursement, options) => {
expenseDraftCall = { expenseType, expenseTypeLabel, requiresApplicationBeforeReimbursement, options }
},
startAiReimbursementAssociationGate: () => {}
},
focusAiModeInput: () => {},
hasInlineAttachmentOcrDetails: () => false,
resolveLatestInlineUserPrompt: () => '',
selectedFiles: { value: [] },
startInlineConversation: () => {},
toast: () => {},
toggleInlineAttachmentOcrDetails: () => {}
})
router.handleInlineSuggestedAction({
label: '继续处理费用报销',
action_type: 'steward_continue_next_task',
payload: {
steward_confirm_flow: true,
flow_id: 'travel_reimbursement',
steward_current_task: {
task_id: 'task-meal-1',
task_type: 'reimbursement',
title: '业务招待费报销',
summary: '报销昨天业务招待费2000元',
ontology_fields: {
expense_type: 'meal',
expense_type_label: '业务招待费',
amount: '2000元',
time_range: '昨天',
reason: '客户招待'
}
},
steward_remaining_tasks: []
}
})
// task2(招待费报销)启动时:费用类型正确、语义预填到草稿、remaining tasks 透传
assert.ok(expenseDraftCall, 'startAiExpenseDraft 应被调用')
assert.equal(expenseDraftCall.expenseType, 'meal')
assert.equal(expenseDraftCall.expenseTypeLabel, '业务招待费')
assert.equal(expenseDraftCall.requiresApplicationBeforeReimbursement, true)
assert.equal(expenseDraftCall.options.prefillValues.amount, '2000元')
assert.equal(expenseDraftCall.options.prefillValues.reason, '客户招待')
assert.equal(expenseDraftCall.options.prefillValues.time_range, '昨天')
assert.deepEqual(expenseDraftCall.options.stewardRemainingTasks, [])
})