fix(wechat): yield schedule handler when scheduled-task intent matches

Stop schedule todo replies from intercepting cancel/list/create automation
requests, and recognize 有哪些 for inbound scheduled task listing.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-29 11:38:17 +08:00
parent a1a921eba6
commit 43ec144540
5 changed files with 56 additions and 1 deletions
+1 -1
View File
@@ -164,7 +164,7 @@ export function parseScheduledTaskIntent(text, { now = Date.now(), timezone = 'A
return { action: 'cancel_scheduled_task' };
}
const wantsList = /(?:查看|看看|列出|我的).{0,12}(?:定时|自动).{0,12}(?:任务|自动化)/u.test(compact)
const wantsList = /(?:查看|看看|列出|我的|有哪些).{0,12}(?:定时|自动).{0,12}(?:任务|自动化)/u.test(compact)
|| /(?:list|show).{0,12}(?:scheduled|automation).{0,12}tasks/iu.test(compact);
if (wantsList) {
return { action: 'list_scheduled_tasks' };
+1
View File
@@ -47,6 +47,7 @@ test('scheduled automation takes precedence over schedule assistant keyword over
test('parses cancel and list intents', () => {
assert.equal(parseScheduledTaskIntent('取消我的定时任务').action, 'cancel_scheduled_task');
assert.equal(parseScheduledTaskIntent('看看我的定时自动任务').action, 'list_scheduled_tasks');
assert.equal(parseScheduledTaskIntent('我有哪些定时任务').action, 'list_scheduled_tasks');
});
test('parses one-shot tonight schedule with task spec', () => {
+5
View File
@@ -1,5 +1,6 @@
import { isScheduleIntent, parseScheduleIntent } from '../../schedule-intent.mjs';
import { formatLocalTime, resolveScheduleTimestamp } from '../../schedule-time.mjs';
import { isScheduledTaskIntent, parseScheduledTaskIntent } from '../../scheduled-task-intent.mjs';
function normalizeHour(value) {
const hour = Number(value);
@@ -160,6 +161,10 @@ export async function handleWechatScheduleIntent({
logger = console,
}) {
if (!scheduleService) return null;
const scheduledTaskIntent = parseScheduledTaskIntent(intent.agentText);
if (isScheduledTaskIntent(scheduledTaskIntent)) {
return null;
}
const scheduleIntent = await resolveScheduleIntent({
text: intent.agentText,
wechatScheduleLlmConfigService,
+32
View File
@@ -182,3 +182,35 @@ test('schedule handler falls through for multi-time reminder requests', async ()
});
assert.equal(reply, null);
});
test('schedule handler yields cancel scheduled task requests to goose', async () => {
let scheduleCalled = false;
const reply = await handleWechatScheduleIntent({
intent: { agentText: '取消定时推送苏州天气任务', msgId: 'msg-cancel-1' },
user: { userId: 'user-123' },
scheduleService: {
async createItem() {
scheduleCalled = true;
return { id: 'item-1' };
},
},
});
assert.equal(reply, null);
assert.equal(scheduleCalled, false);
});
test('schedule handler yields list scheduled task requests to scheduled-task handler', async () => {
let scheduleCalled = false;
const reply = await handleWechatScheduleIntent({
intent: { agentText: '我有哪些定时任务', msgId: 'msg-list-1' },
user: { userId: 'user-123' },
scheduleService: {
async createItem() {
scheduleCalled = true;
return { id: 'item-1' };
},
},
});
assert.equal(reply, null);
assert.equal(scheduleCalled, false);
});
+17
View File
@@ -86,3 +86,20 @@ test('handleWechatScheduledTaskIntent still lists tasks', async () => {
});
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);
});