From 6ba95c622928f8ff6d9ca5e7737921619f546fff Mon Sep 17 00:00:00 2001 From: john Date: Wed, 12 Aug 2026 01:36:38 +0800 Subject: [PATCH] fix(scheduled-task): reject meta-only phrases in taskSpec parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Treat hollow requests like「我要做一个定时执行任务」as missing taskSpec so WeChat preflight asks for both schedule and executable content instead of accepting「执行」as a deliverable task description. Co-authored-by: Cursor --- scheduled-task-intent.mjs | 22 ++++++++++++++++++++++ scheduled-task-intent.test.mjs | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/scheduled-task-intent.mjs b/scheduled-task-intent.mjs index b91366c..d2e5e57 100644 --- a/scheduled-task-intent.mjs +++ b/scheduled-task-intent.mjs @@ -25,6 +25,23 @@ const WEEKDAY_LABELS = [ ['周六', '星期六'], ]; +const META_TASK_SPEC_PATTERNS = [ + /^我要?(?:做|创建|设置|弄)?(?:一个|个)?(?:定时(?:自动)?)?执行(?:任务)?$/u, + /^帮我?(?:做|创建|设置|弄)?(?:一个|个)?(?:定时(?:自动)?)?执行(?:任务)?$/u, + /^请?(?:帮我)?(?:做|创建|设置|弄)?(?:一个|个)?(?:定时(?:自动)?)?执行(?:任务)?$/u, + /^定时(?:自动)?执行(?:任务)?$/u, + /^执行(?:任务)?$/u, + /^做(?:一个|个)?(?:定时(?:自动)?)?(?:执行)?任务$/u, + /^创建(?:一个|个)?定时(?:自动)?执行(?:任务)?$/u, + /^想(?:要)?(?:做|创建|设置)?(?:一个|个)?(?:定时(?:自动)?)?执行(?:任务)?$/u, +]; + +function isMetaScheduledTaskSpec(spec) { + const normalized = String(spec ?? '').replace(/\s+/g, '').trim(); + if (!normalized) return true; + return META_TASK_SPEC_PATTERNS.some((pattern) => pattern.test(normalized)); +} + function wantsScheduledTaskAutomation(compact) { if (SCHEDULE_MARKERS.test(compact)) return true; if (!RECURRENCE_MARKERS.test(compact)) return false; @@ -48,6 +65,7 @@ function extractScheduledTaskSpec(text) { const original = String(text ?? '').trim(); if (!original) return null; let spec = original + .replace(/^(?:不是|别是|并非)(?:待办|代办|提醒|日程|闹钟)[,,、::\s]*/u, '') .replace( /^(?:帮我)?(?:设|设置|创建|添加|想创建)(?:一个|个)?(?:定时(?:自动)?任务|定时执行任务)?[::,,、\s]*/u, '', @@ -62,9 +80,12 @@ function extractScheduledTaskSpec(text) { ) .replace(/(?:周[一二三四五六日天]|星期[一二三四五六日天])/gu, ' ') .replace(/(?:帮我|请|麻烦)/gu, ' ') + .replace(/^执行[,,、::\s]+/u, '') + .replace(/[,,、::\s]+执行$/u, '') .replace(/\s+/g, ' ') .trim(); if (!spec || spec.length < 3) return null; + if (isMetaScheduledTaskSpec(spec)) return null; if (!EXECUTE_VERBS.test(spec.replace(/\s+/g, ''))) return null; return spec; } @@ -302,6 +323,7 @@ export function formatScheduledTaskListReply(tasks = []) { export { extractScheduledTaskSpec, + isMetaScheduledTaskSpec, parseWeekday, resolveOnceRunAtLocal, }; diff --git a/scheduled-task-intent.test.mjs b/scheduled-task-intent.test.mjs index 1d4d56b..b5bfcb4 100644 --- a/scheduled-task-intent.test.mjs +++ b/scheduled-task-intent.test.mjs @@ -90,3 +90,24 @@ test('isScheduledTaskIntent excludes none', () => { assert.equal(isScheduledTaskIntent({ action: 'create_scheduled_task' }), true); assert.equal(isScheduledTaskIntent({ action: 'none' }), false); }); + +test('meta scheduled-task phrases require task_spec clarification', () => { + for (const text of [ + '我要做一个定时执行任务', + '定时自动执行任务', + '不是待办,定时执行任务', + ]) { + const intent = parseScheduledTaskIntent(text); + assert.equal(intent.action, 'create_scheduled_task', text); + assert.ok(intent.needsClarification?.includes('task_spec'), text); + assert.ok(intent.needsClarification?.includes('schedule'), text); + assert.equal(extractScheduledTaskSpec(text), null, text); + } +}); + +test('combined phrase keeps substantive taskSpec after time prefix', () => { + const text = '帮我创建一个定时执行任务,23:00执行,搜索今日新闻'; + const intent = parseScheduledTaskIntent(text); + assert.equal(intent.needsClarification, undefined); + assert.match(intent.taskSpec, /搜索今日新闻/u); +});