Files
memind/wechat/intent/classifier.mjs
T
john 570ecbd1b0 feat(wechat): add WX gate evidence and v1.49 103 cutover runbook
Prioritize scheduled-task intent over page.generate for automation phrases, add run-wechat-gate-evidence.mjs for WX-01..13, and document 103 maintenance-window steps for Goose v1.49.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 15:01:32 +08:00

108 lines
3.7 KiB
JavaScript

import { isScheduledTaskIntent, parseScheduledTaskIntent } from '../../scheduled-task-intent.mjs';
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);
}
const scheduledTaskIntent = parseScheduledTaskIntent(text);
if (isScheduledTaskIntent(scheduledTaskIntent)) {
return withChannelMeta({ kind: 'chat.general', 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';
}