import { parseWechatChannelPrefix, WECHAT_CHANNEL_PREFIX } from './channel-prefix.mjs'; import { CONNECTIVITY_TEST_PATTERN, GREETING_PATTERN, STATUS_PROBE_PATTERN, isPageGenerateText, isTopicResetText, wantsDocxDownload, } from './patterns.mjs'; import { WECHAT_SESSION_ACTION } from './session-action.mjs'; /** * @typedef {object} WechatPageGenerateIntent * @property {'page.generate'} kind * @property {string} topic * @property {boolean} wantsDocx * * @typedef {object} WechatSessionResetIntent * @property {'session.reset'} kind * @property {string} sessionAction * * @typedef {object} WechatStatusProbeIntent * @property {'status.probe'} kind * * @typedef {object} WechatGreetingIntent * @property {'greeting'} kind * * @typedef {object} WechatConnectivityTestIntent * @property {'connectivity.test'} kind * * @typedef {object} WechatGeneralChatIntent * @property {'chat.general'} kind * @property {string} text * * @typedef {object} WechatUnsupportedIntent * @property {'unsupported'} kind * @property {string} msgType * * @typedef {WechatPageGenerateIntent|WechatSessionResetIntent|WechatStatusProbeIntent|WechatGreetingIntent|WechatConnectivityTestIntent|WechatGeneralChatIntent|WechatUnsupportedIntent} WechatIntent */ /** * Classify a normalized WeChat inbound intent (from wechat-mp normalizeWechatInboundIntent). * @param {{ msgType?: string, agentText?: string, displayText?: string }} intent * @returns {WechatIntent} */ function withChannelMeta(result, channelPrefix) { if (!channelPrefix) return result; return { ...result, channelPrefix }; } export function classifyWechatIntent(intent) { const msgType = String(intent?.msgType ?? 'text').toLowerCase(); const rawText = String(intent?.agentText ?? intent?.displayText ?? '').trim(); const { channel: channelPrefix, body: text } = parseWechatChannelPrefix(rawText); if (msgType === 'text' || msgType === 'voice') { if (isTopicResetText(text)) { return withChannelMeta( { kind: 'session.reset', sessionAction: WECHAT_SESSION_ACTION.RESET }, channelPrefix, ); } if (STATUS_PROBE_PATTERN.test(text)) { return withChannelMeta({ kind: 'status.probe' }, channelPrefix); } if (GREETING_PATTERN.test(text.replace(/[!!。.\s]+$/g, ''))) { return withChannelMeta({ kind: 'greeting' }, channelPrefix); } if (CONNECTIVITY_TEST_PATTERN.test(text.replace(/[!!。.\s]+$/g, ''))) { return withChannelMeta({ kind: 'connectivity.test' }, channelPrefix); } if (channelPrefix === WECHAT_CHANNEL_PREFIX.CHAT) { return withChannelMeta({ kind: 'chat.general', text }, channelPrefix); } if (channelPrefix === WECHAT_CHANNEL_PREFIX.PAGE) { return withChannelMeta({ kind: 'page.generate', topic: text, wantsDocx: wantsDocxDownload(text), }, channelPrefix); } if (isPageGenerateText(text)) { return withChannelMeta({ kind: 'page.generate', topic: text, wantsDocx: wantsDocxDownload(text), }, channelPrefix); } return withChannelMeta({ kind: 'chat.general', text }, channelPrefix); } if (msgType === 'event') { return { kind: 'unsupported', msgType: 'event' }; } return { kind: 'chat.general', text: text || `[${msgType}]` }; } export function isPageGenerateIntent(intent) { return classifyWechatIntent(intent).kind === 'page.generate'; }