feat(wechat): migrate schedule and sync handlers into wechat package

Extract schedule, greeting/status/connectivity replies, chat-general prompt, and display-name helpers from wechat-mp.mjs. Route sync intents via classifyWechatIntent and add channel isolation CI check.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-04 13:48:47 +08:00
parent fafc1fe7fd
commit 031c6e086a
9 changed files with 435 additions and 300 deletions
+39
View File
@@ -10,7 +10,10 @@ import {
selectSendableHtmlArtifacts,
verifyPageArtifactContent,
} from './verify/page-artifact.mjs';
import { guardScheduleConfirmationReply, looksLikeScheduleConfirmation } from './handlers/schedule-guard.mjs';
import { resolvePageGenerateOutcome } from './handlers/page-generate.mjs';
import { buildGreetingText, resolveSyncReply } from './handlers/sync-replies.mjs';
import { buildWechatAgentPrompt } from './prompts/chat-general.mjs';
test('classifyWechatIntent detects page.generate', () => {
const intent = classifyWechatIntent({
@@ -50,6 +53,42 @@ test('selectSendableHtmlArtifacts never returns stub html', () => {
assert.equal(isStubPublicHtmlContent('<html>服务号自动补出简版页面</html>'), true);
});
test('resolveSyncReply handles greeting and status probes', () => {
const user = { nickname: '唐' };
assert.match(
resolveSyncReply(classifyWechatIntent({ msgType: 'text', agentText: '你好' }), user, {
statusFallbackText: '处理中',
}),
/唐/,
);
assert.match(
resolveSyncReply(classifyWechatIntent({ msgType: 'text', agentText: '??' }), user, {
statusFallbackText: '处理中',
}),
/我在这边/,
);
});
test('buildWechatAgentPrompt lives in wechat prompts package', () => {
const prompt = buildWechatAgentPrompt({
msgType: 'text',
agentText: '明天早上 6 点跑步,5 点半提醒我',
});
assert.match(prompt, /schedule-assistant/);
});
test('schedule confirmation guard blocks false positives', async () => {
assert.equal(looksLikeScheduleConfirmation('已经帮你设置好了待办提醒'), true);
const guarded = await guardScheduleConfirmationReply({
replyText: '已经帮你设置好了待办提醒',
scheduleService: { listItemsBySourceMessage: async () => [] },
userId: 'user-1',
sourceMessageId: 'msg-1',
logger: null,
});
assert.match(guarded, /不能算设置成功/);
});
test('resolvePageGenerateOutcome fails when only stub artifacts exist', () => {
const outcome = resolvePageGenerateOutcome({
reply: { text: '页面已生成 https://m.tkmind.cn/MindSpace/u/public/tang-poem.html' },