import assert from 'node:assert/strict'; import test from 'node:test'; import { buildScheduledTaskCreatePayload, extractScheduledTaskSpec, isScheduledTaskIntent, parseScheduledTaskIntent, resolveOnceRunAtLocal, shouldUseScheduledTaskAutomation, } from './scheduled-task-intent.mjs'; import { shouldUseScheduleAssistant } from './schedule-intent.mjs'; test('detects daily news page automation intent', () => { assert.equal(shouldUseScheduledTaskAutomation('每天6点帮我做今日新闻页面'), true); const intent = parseScheduledTaskIntent('每天6点帮我做今日新闻页面'); assert.equal(intent.action, 'create_scheduled_task'); assert.equal(intent.recurrence, 'daily'); assert.equal(intent.hour, 6); assert.equal(intent.minute, 0); assert.match(intent.taskSpec, /今日新闻页面/u); assert.equal(intent.needsClarification, undefined); }); test('detects explicit scheduled task phrase', () => { assert.equal(shouldUseScheduledTaskAutomation('帮我设一个定时自动任务'), true); const intent = parseScheduledTaskIntent('帮我设一个定时自动任务'); assert.equal(intent.action, 'create_scheduled_task'); assert.ok(intent.needsClarification?.includes('schedule')); assert.ok(intent.needsClarification?.includes('task_spec')); }); test('does not capture daily todo digest', () => { assert.equal(shouldUseScheduledTaskAutomation('每天早上7点把当天待办发给我'), false); assert.equal(parseScheduledTaskIntent('每天早上7点把当天待办发给我').action, 'none'); }); test('does not capture plain reminders', () => { assert.equal(shouldUseScheduledTaskAutomation('明天下午三点提醒我开会'), false); assert.equal(shouldUseScheduleAssistant('明天下午三点提醒我开会'), true); }); test('scheduled automation takes precedence over schedule assistant keyword overlap', () => { assert.equal(shouldUseScheduledTaskAutomation('每天6点定时任务做新闻页'), true); assert.equal(shouldUseScheduleAssistant('每天6点定时任务做新闻页'), false); }); test('parses cancel and list intents', () => { assert.equal(parseScheduledTaskIntent('取消我的定时任务').action, 'cancel_scheduled_task'); assert.equal(parseScheduledTaskIntent('看看我的定时自动任务').action, 'list_scheduled_tasks'); }); test('parses one-shot tonight schedule with task spec', () => { const intent = parseScheduledTaskIntent('我想创建一个定时执行任务,今晚 21:45 分执行做新闻页面'); assert.equal(intent.action, 'create_scheduled_task'); assert.equal(intent.recurrence, 'once'); assert.match(intent.runAtLocal, /^\d{4}-\d{2}-\d{2} 21:45$/); assert.match(intent.taskSpec, /新闻页面/u); }); test('buildScheduledTaskCreatePayload maps parsed intent', () => { const intent = parseScheduledTaskIntent('每天6点帮我做今日新闻页面'); const payload = buildScheduledTaskCreatePayload(intent, { userId: 'user-1', sourceMessageId: 'msg-1', sourceText: '每天6点帮我做今日新闻页面', }); assert.equal(payload.userId, 'user-1'); assert.equal(payload.recurrence, 'daily'); assert.equal(payload.hour, 6); assert.match(payload.taskSpec, /今日新闻页面/u); }); test('extractScheduledTaskSpec keeps executable content', () => { assert.match( extractScheduledTaskSpec('每天6点帮我做今日新闻页面'), /今日新闻页面/u, ); }); test('resolveOnceRunAtLocal returns future local datetime', () => { const now = Date.parse('2026-08-11T10:00:00+08:00'); const runAtLocal = resolveOnceRunAtLocal('今晚 21:45 做新闻页', '今晚21:45做新闻页', { timezone: 'Asia/Shanghai', now, }); assert.match(runAtLocal, /^2026-08-11 21:45$/); }); 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); });