9b4a25799f
Replace fixed ackText with a rule-based AckProvider that picks response templates by message type and intent (translate, summary, rewrite, poster, ppt, mindmap, code, search, schedule). Pure sync, zero I/O, auto-falls back to config.ackText on any error. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
75 lines
3.3 KiB
JavaScript
75 lines
3.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { parseScheduleIntent, shouldUseScheduleAssistant } from './schedule-intent.mjs';
|
|
import { nextDailyRunAt } from './schedule-time.mjs';
|
|
|
|
test('parses daily 7am todo digest request', () => {
|
|
const intent = parseScheduleIntent('每天早上 7 点给我发一天的待办记录');
|
|
assert.equal(intent.action, 'create_daily_todo_digest');
|
|
assert.equal(intent.hour, 7);
|
|
assert.equal(intent.minute, 0);
|
|
});
|
|
|
|
test('daily todo digest asks for time when missing', () => {
|
|
const intent = parseScheduleIntent('每天给我发一天的待办记录');
|
|
assert.equal(intent.action, 'create_daily_todo_digest');
|
|
assert.deepEqual(intent.needsClarification, ['digest_time']);
|
|
});
|
|
|
|
test('parses balance low reminder request', () => {
|
|
const intent = parseScheduleIntent('余额低于 20 元提醒我');
|
|
assert.equal(intent.action, 'create_balance_alert');
|
|
assert.equal(intent.thresholdCents, 2000);
|
|
});
|
|
|
|
test('balance reminder asks for threshold when missing', () => {
|
|
const intent = parseScheduleIntent('余额不足提醒我');
|
|
assert.equal(intent.action, 'create_balance_alert');
|
|
assert.deepEqual(intent.needsClarification, ['threshold']);
|
|
});
|
|
|
|
test('parses plain todo record request with quoted title', () => {
|
|
const intent = parseScheduleIntent('帮我记一下「🍽️ 跟段吃饭」');
|
|
assert.equal(intent.action, 'create_todo');
|
|
assert.equal(intent.title, '🍽️ 跟段吃饭');
|
|
});
|
|
|
|
test('plain todo record request asks for title when missing', () => {
|
|
const intent = parseScheduleIntent('帮我记一下');
|
|
assert.equal(intent.action, 'create_todo');
|
|
assert.deepEqual(intent.needsClarification, ['todo_title']);
|
|
});
|
|
|
|
test('parses setting a todo with common colloquial wording', () => {
|
|
const intent = parseScheduleIntent('帮我设置一个代办一会儿跟段段吃饭');
|
|
assert.equal(intent.action, 'create_todo');
|
|
assert.equal(intent.title, '一会儿跟段段吃饭');
|
|
});
|
|
|
|
test('parses typo variant for todo wording', () => {
|
|
const intent = parseScheduleIntent('帮我设置一个带办明天交周报');
|
|
assert.equal(intent.action, 'schedule_agent');
|
|
});
|
|
|
|
test('schedule assistant catches reminder-style requests', () => {
|
|
assert.equal(shouldUseScheduleAssistant('明天早上六点去跑步,五点半提醒我'), true);
|
|
assert.equal(shouldUseScheduleAssistant('帮我做个页面'), false);
|
|
});
|
|
|
|
test('schedule assistant catches production ASR typo for todo', () => {
|
|
const intent = parseScheduleIntent('明天早上六点去跑步帮我设下一个代拜');
|
|
assert.equal(intent.action, 'schedule_agent');
|
|
assert.equal(shouldUseScheduleAssistant('明天早上六点去跑步帮我设下一个代拜'), true);
|
|
});
|
|
|
|
test('reminder todo request routes to schedule assistant instead of plain todo shortcut', () => {
|
|
const intent = parseScheduleIntent('帮我设置一个代办明天早上六点去跑步记得在五点半的时候提醒我');
|
|
assert.equal(intent.action, 'schedule_agent');
|
|
});
|
|
|
|
test('nextDailyRunAt rolls to tomorrow when today time has passed', () => {
|
|
const now = Date.UTC(2026, 5, 17, 23, 30, 0); // 2026-06-18 07:30 Asia/Shanghai
|
|
const next = nextDailyRunAt({ hour: 7, minute: 0, timezone: 'Asia/Shanghai', now });
|
|
assert.equal(next, Date.UTC(2026, 5, 18, 23, 0, 0)); // 2026-06-19 07:00 Asia/Shanghai
|
|
});
|