Files
X-Financial/web/tests/workbench-application-intent.test.mjs

171 lines
6.2 KiB
JavaScript
Raw Normal View History

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import {
ASSISTANT_SCOPE_SESSION_APPLICATION,
ASSISTANT_SCOPE_SESSION_EXPENSE,
ASSISTANT_SCOPE_SESSION_KNOWLEDGE,
ASSISTANT_SCOPE_SESSION_STEWARD,
inferAssistantScopeTarget
} from '../src/utils/assistantSessionScope.js'
import {
resolveWorkbenchSessionTypeFromOntology
} from '../src/utils/workbenchAssistantIntent.js'
const appShellRouteView = readFileSync(
fileURLToPath(new URL('../src/views/AppShellRouteView.vue', import.meta.url)),
'utf8'
)
const appShellComposable = readFileSync(
fileURLToPath(new URL('../src/composables/useAppShell.js', import.meta.url)),
'utf8'
)
const assistantScript = readFileSync(
fileURLToPath(new URL('../src/views/scripts/TravelReimbursementCreateView.js', import.meta.url)),
'utf8'
)
test('workbench prompt applies travel phrases to application assistant scope', () => {
assert.equal(inferAssistantScopeTarget('申请出差'), ASSISTANT_SCOPE_SESSION_APPLICATION)
assert.equal(
inferAssistantScopeTarget('去北京出差3天支撑国网仿生产环境部署'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
inferAssistantScopeTarget('去国网出差3天协助仿生产环境部署'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
inferAssistantScopeTarget('下周去上海支撑客户系统上线预计3天'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
inferAssistantScopeTarget('安排去深圳客户现场验收项目'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
inferAssistantScopeTarget('准备去国网现场做仿生产环境部署差旅3天'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
inferAssistantScopeTarget('2月20-23日去上海出差辅助国网仿生产环境部署'),
ASSISTANT_SCOPE_SESSION_STEWARD
)
assert.equal(
inferAssistantScopeTarget('我要报销去北京的费用'),
ASSISTANT_SCOPE_SESSION_EXPENSE
)
assert.equal(
inferAssistantScopeTarget('我要报销去北京出差的费用'),
ASSISTANT_SCOPE_SESSION_EXPENSE
)
assert.equal(
inferAssistantScopeTarget('去北京出差报销标准是多少'),
ASSISTANT_SCOPE_SESSION_KNOWLEDGE
)
assert.notEqual(
inferAssistantScopeTarget('昨天去北京出差花了1000元'),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.match(appShellComposable, /fetchOntologyParse/)
assert.match(appShellComposable, /resolveWorkbenchSessionTypeFromOntology/)
assert.match(appShellComposable, /resolveWorkbenchSessionTypeFallback/)
assert.match(appShellRouteView, /:initial-session-type="smartEntryContext\.sessionType"/)
assert.match(assistantScript, /initialSessionType:\s*\{[\s\S]*type:\s*String/)
})
test('workbench model routing maps ontology result before entering assistant', () => {
const travelOntology = {
scenario: 'expense',
intent: 'draft',
entities: [
{ type: 'expense_type', normalized_value: 'travel' }
]
}
const reimbursementOntology = {
scenario: 'expense',
intent: 'draft',
entities: [
{ type: 'expense_type', normalized_value: 'travel' }
]
}
const applicationOntology = {
scenario: 'expense',
intent: 'draft',
entities: [
{ type: 'document_type', normalized_value: 'expense_application' },
{ type: 'workflow_stage', normalized_value: 'pre_approval' }
]
}
assert.equal(
resolveWorkbenchSessionTypeFromOntology(
travelOntology,
'下周去上海支撑客户系统上线预计3天',
ASSISTANT_SCOPE_SESSION_EXPENSE
),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
assert.equal(
resolveWorkbenchSessionTypeFromOntology(
travelOntology,
'2月20-23日去上海出差辅助国网仿生产环境部署',
ASSISTANT_SCOPE_SESSION_APPLICATION
),
ASSISTANT_SCOPE_SESSION_STEWARD
)
assert.equal(
resolveWorkbenchSessionTypeFromOntology(
reimbursementOntology,
'我要报销去北京出差的费用',
ASSISTANT_SCOPE_SESSION_APPLICATION
),
ASSISTANT_SCOPE_SESSION_EXPENSE
)
assert.equal(
resolveWorkbenchSessionTypeFromOntology(
{ scenario: 'expense', intent: 'query', entities: reimbursementOntology.entities },
'去北京出差报销标准是多少',
ASSISTANT_SCOPE_SESSION_KNOWLEDGE
),
ASSISTANT_SCOPE_SESSION_KNOWLEDGE
)
assert.equal(
resolveWorkbenchSessionTypeFromOntology(
applicationOntology,
'国网仿生产环境部署',
ASSISTANT_SCOPE_SESSION_EXPENSE
),
ASSISTANT_SCOPE_SESSION_APPLICATION
)
})
test('workbench smart entry blocks unsupported non-business input before ontology parsing', () => {
const openSmartEntryStart = appShellComposable.indexOf('async function openSmartEntry(payload')
const closeSmartEntryStart = appShellComposable.indexOf('function closeSmartEntry(')
assert.ok(openSmartEntryStart >= 0, 'expected an openSmartEntry entry point')
assert.ok(closeSmartEntryStart > openSmartEntryStart, 'expected closeSmartEntry to follow openSmartEntry')
const openSmartEntryBlock = appShellComposable.slice(openSmartEntryStart, closeSmartEntryStart)
const guardIndex = openSmartEntryBlock.indexOf('resolveAssistantScopeGuard(')
const blockedIndex = openSmartEntryBlock.indexOf('scopeGuard?.blocked')
const conversationIndex = openSmartEntryBlock.indexOf('buildUnsupportedBusinessScopeConversation(prompt')
const sessionTypeResolveIndex = openSmartEntryBlock.indexOf('resolveSmartEntrySessionType(payload)')
assert.ok(guardIndex >= 0, 'expected smart entry to use the business scope guard')
assert.ok(blockedIndex >= 0, 'expected smart entry to short-circuit blocked inputs')
assert.ok(conversationIndex >= 0, 'expected blocked smart entry inputs to seed an assistant conversation')
assert.ok(sessionTypeResolveIndex >= 0, 'expected smart entry to delegate session resolution')
assert.ok(
blockedIndex < sessionTypeResolveIndex,
'expected blocked inputs to stop before ontology-driven session resolution'
)
assert.ok(
conversationIndex < sessionTypeResolveIndex,
'expected unsupported input guidance to be prepared before session resolution'
)
})