Files
memind/wechat/handlers/scheduled-task.test.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

290 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import assert from 'node:assert/strict';
import test from 'node:test';
import { handleWechatScheduledTaskIntent } from './scheduled-task.mjs';
test('handleWechatScheduledTaskIntent passes create requests to goose', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '每天6点帮我做今日新闻页面',
msgId: 'msg-1',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async createTask() {
throw new Error('should not create from inbound regex');
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent passes incomplete create requests to goose', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '帮我设一个定时自动任务',
msgId: 'msg-1',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async createTask() {
throw new Error('should not create from inbound regex');
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent passes scheduled page automation to goose even when page keywords appear', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '我想创建一个定时执行任务,今晚 21:45 分执行做新闻页面',
msgId: 'msg-sched-page-1',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async listTasks() {
throw new Error('should not list for create_scheduled_task');
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent yields page.generate requests to cursor/goose path', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '帮我做一个苏州天气展示页面',
msgId: 'msg-page-1',
},
user: { userId: 'user-tang' },
scheduledTaskService: {
async listTasks() {
throw new Error('should not list for page.generate');
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent cancels via manage llm when task is identified', async () => {
const calls = [];
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '取消定时推送苏州天气任务',
msgId: 'msg-123-1',
},
user: { userId: 'user-123' },
scheduledTaskService: {
async listTasks() {
return [{
id: 'task-suzhou',
title: '每天早上6:30推送苏州市天气预报',
recurrence: 'daily',
hour: 6,
minute: 30,
timezone: 'Asia/Shanghai',
}];
},
async cancelTask(payload) {
calls.push(payload);
return {
id: 'task-suzhou',
title: '每天早上6:30推送苏州市天气预报',
status: 'cancelled',
};
},
},
wechatScheduledTaskManageLlmConfigService: {
async isManageLlmEnabled() {
return true;
},
async getConfig() {
return { modelProviderKeyId: 'key-1', model: 'deepseek-chat' };
},
},
llmProviderService: {
async createChatCompletion() {
return {
ok: true,
reply: JSON.stringify({ action: 'cancel', taskId: 'task-suzhou' }),
};
},
},
});
assert.match(reply, /已取消定时任务/u);
assert.deepEqual(calls, [{ userId: 'user-123', taskId: 'task-suzhou' }]);
});
test('handleWechatScheduledTaskIntent passes cancel to goose when manage llm is disabled', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '取消定时推送苏州天气任务',
msgId: 'msg-123-2',
},
user: { userId: 'user-123' },
scheduledTaskService: {
async listTasks() {
return [
{ id: 'task-1', title: '苏州天气', recurrence: 'daily', hour: 6, minute: 30, timezone: 'Asia/Shanghai' },
{ id: 'task-2', title: '新闻早报', recurrence: 'daily', hour: 5, minute: 30, timezone: 'Asia/Shanghai' },
];
},
async cancelTask() {
throw new Error('should not cancel from inbound when llm disabled');
},
},
wechatScheduledTaskManageLlmConfigService: {
async isManageLlmEnabled() {
return false;
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent outage-fallback cancels sole active task when manage llm is unavailable', async () => {
const calls = [];
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '取消定时推送苏州天气任务',
msgId: 'msg-123-outage',
},
user: { userId: 'user-123' },
scheduledTaskService: {
async listTasks() {
return [{
id: 'task-suzhou',
title: '每天早上6:30推送苏州市天气预报',
recurrence: 'daily',
hour: 6,
minute: 30,
timezone: 'Asia/Shanghai',
}];
},
async cancelTask(payload) {
calls.push(payload);
return {
id: 'task-suzhou',
title: '每天早上6:30推送苏州市天气预报',
status: 'cancelled',
};
},
},
wechatScheduledTaskManageLlmConfigService: {
async isManageLlmEnabled() {
return true;
},
async getConfig() {
return { modelProviderKeyId: 'deepseek-key', model: 'deepseek-chat' };
},
},
llmProviderService: {
async listKeys() {
return [{ id: 'deepseek-key', name: 'DeepSeek', status: 'active', defaultModel: 'deepseek-chat', models: ['deepseek-chat'] }];
},
async createChatCompletion() {
return { ok: false, status: 402, message: '{"error":{"message":"Insufficient Balance"}}' };
},
},
});
assert.match(reply, /已取消定时任务/u);
assert.deepEqual(calls, [{ userId: 'user-123', taskId: 'task-suzhou' }]);
});
test('handleWechatScheduledTaskIntent returns clarify message when manage llm is ambiguous', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '帮我取消定时任务',
msgId: 'msg-123-3',
},
user: { userId: 'user-tang' },
scheduledTaskService: {
async listTasks() {
return [
{ id: 'task-news', title: '每日新闻早报页面(5:30', recurrence: 'daily', hour: 5, minute: 30 },
{ id: 'task-checkin', title: '每日打卡提醒', recurrence: 'daily', hour: 18, minute: 0 },
];
},
},
wechatScheduledTaskManageLlmConfigService: {
async isManageLlmEnabled() {
return true;
},
async getConfig() {
return { modelProviderKeyId: 'key-1', model: 'deepseek-chat' };
},
},
llmProviderService: {
async createChatCompletion() {
return {
ok: true,
reply: JSON.stringify({
action: 'clarify',
message: '你是想取消 5:30 新闻早报,还是 18:00 打卡提醒?',
}),
};
},
},
});
assert.match(reply, /新闻早报/u);
});
test('handleWechatScheduledTaskIntent ignores non automation text', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '明天下午三点提醒我开会',
msgId: 'msg-1',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async createTask() {
throw new Error('should not create');
},
},
});
assert.equal(reply, null);
});
test('handleWechatScheduledTaskIntent still lists tasks', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '看看我的定时自动任务',
msgId: 'msg-1',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async listTasks() {
return [{ title: '新闻页面', recurrence: 'daily', hour: 6, minute: 0, timezone: 'Asia/Shanghai' }];
},
},
});
assert.match(reply, /新闻页面/u);
});
test('handleWechatScheduledTaskIntent lists tasks for 有哪些 phrasing', async () => {
const reply = await handleWechatScheduledTaskIntent({
intent: {
msgType: 'text',
agentText: '我有哪些定时任务',
msgId: 'msg-2',
},
user: { userId: 'user-1' },
scheduledTaskService: {
async listTasks() {
return [{ title: '苏州天气', recurrence: 'daily', hour: 6, minute: 30, timezone: 'Asia/Shanghai' }];
},
},
});
assert.match(reply, /苏州天气/u);
});