import assert from 'node:assert/strict' import test from 'node:test' import { buildLocalExtractionProgressMessages, buildLocalIntentPreview, inferLocalFlowCandidates, shouldRequestExpenseIntentConfirmation, shouldRequestExpenseSceneSelection, summarizeSemanticIntentDetail } from '../src/utils/reimbursementTextInference.js' const ridingFareMessage = '业务发生时间:2026-03-04,送客户去林萃小区办事,请报销乘车费用' test('local flow intent preview names transport expense for riding fare text', () => { const candidates = inferLocalFlowCandidates(ridingFareMessage) assert.equal(candidates.time, '2026-03-04') assert.equal(candidates.event, '交通出行') assert.equal(candidates.expenseType, '交通费') assert.match(buildLocalIntentPreview(ridingFareMessage), /交通费/) assert.ok( buildLocalExtractionProgressMessages(ridingFareMessage).some( (item) => item.includes('交通出行') && item.includes('交通费') ) ) assert.ok( buildLocalExtractionProgressMessages(ridingFareMessage).some( (item) => item.includes('正在判断待补项') && !item.includes('客户名称') && !item.includes('参与人员') ) ) }) test('local flow recognizes broader reimbursement scene keywords', () => { assert.equal(inferLocalFlowCandidates('报销会议场地费').expenseType, '会务费') assert.equal(inferLocalFlowCandidates('报销打印纸和硒鼓').expenseType, '办公用品费') assert.equal(inferLocalFlowCandidates('报销培训课程费').expenseType, '培训费') assert.equal(inferLocalFlowCandidates('报销手机话费和流量费').expenseType, '通讯费') assert.equal(inferLocalFlowCandidates('报销员工体检费').expenseType, '福利费') }) test('semantic intent detail includes recognized expense type', () => { assert.equal( summarizeSemanticIntentDetail({ scenario: 'expense', intent: 'draft', entities_json: [ { type: 'expense_type', value: '交通', normalized_value: 'transport' } ] }), '已识别为报销场景,当前目标是信息核对,费用类型为交通费' ) }) test('ambiguous expense prompt waits for scene selection before extraction preview', () => { const ambiguousMessage = '业务发生时间:2026-02-20 至 2026-02-23,去上海支持上海电力部署项目,申请报销' assert.equal(shouldRequestExpenseSceneSelection(ambiguousMessage), true) assert.match(buildLocalIntentPreview(ambiguousMessage), /需要先由用户选择场景/) assert.doesNotMatch(buildLocalIntentPreview(ambiguousMessage), /草稿生成/) }) test('clear expense type does not request scene selection', () => { const travelMessage = '业务发生时间:2026-02-20 至 2026-02-23,去上海出差支持上海电力部署项目,申请差旅报销' assert.equal(shouldRequestExpenseSceneSelection(travelMessage), false) assert.match(buildLocalIntentPreview(travelMessage), /差旅费/) }) test('business activity without expense intent asks for reimbursement confirmation first', () => { const businessMessage = '去上海电力支撑项目部署' assert.equal(shouldRequestExpenseIntentConfirmation(businessMessage), true) assert.match(buildLocalIntentPreview(businessMessage), /是否发起报销尚不明确/) assert.equal(shouldRequestExpenseSceneSelection(businessMessage), false) }) test('non-reimbursement assistant sessions do not trigger reimbursement scene selection', () => { const ambiguousMessage = '业务发生时间:2026-02-20 至 2026-02-23,去上海支持上海电力部署项目,申请报销' assert.equal(shouldRequestExpenseSceneSelection(ambiguousMessage, { sessionType: 'application' }), false) assert.equal(shouldRequestExpenseIntentConfirmation('去上海电力支撑项目部署', { sessionType: 'approval' }), false) assert.match(buildLocalIntentPreview(ambiguousMessage, 'application'), /费用申请事项/) assert.match(buildLocalIntentPreview('查一下待我审核的单据', 'approval'), /审核处理事项/) }) test('explicit technical operation does not ask for reimbursement confirmation', () => { const operationMessage = '去上海电力支撑项目部署,帮我整理服务器部署步骤' assert.equal(shouldRequestExpenseIntentConfirmation(operationMessage), false) })