d58dc2a251
Introduce Draft → Confirm → Commit flow for WeChat schedule intents behind feature flags, plus h5_tasks dual-write/read aggregation and rollout scripts so reminders and automations get explicit user confirmation before persisting. Co-authored-by: Cursor <cursoragent@cursor.com>
65 lines
2.9 KiB
JavaScript
65 lines
2.9 KiB
JavaScript
import { formatUnifiedTaskListReply } from './task-unified-service.mjs';
|
||
|
||
function normalizeCompact(text) {
|
||
return String(text ?? '').replace(/\s+/g, '').trim();
|
||
}
|
||
|
||
/** Layer 0: 只读查询,禁止 Draft / Commit */
|
||
export function detectQueryGuard(text) {
|
||
const compact = normalizeCompact(text);
|
||
if (!compact) return false;
|
||
|
||
if (/看看我的待办/u.test(compact)) return true;
|
||
if (/查看我的(?:待办|日程|行程|计划)/u.test(compact)) return true;
|
||
if (/(?:列出|看看).{0,8}(?:定时|自动).{0,8}任务/u.test(compact)) return true;
|
||
if (/(?:有没有|是否有).{0,16}(?:定时|自动).{0,8}任务/u.test(compact)) return true;
|
||
if (/(?:取消|停止|关闭|删除).{0,8}(?:定时|提醒|任务)/u.test(compact)) return false;
|
||
|
||
const queryCue = /(?:查一下|查询|看看有没有|有没有(?!新的)|是否有|是否已有|是否还在|是否设置|我有哪些|有哪些提醒|有没有执行|有没有设置)/u.test(compact);
|
||
const createCue = /(?:帮我设置|请设置|创建|添加|记一下|设个|设一个|每天|每日|帮我每天|到点提醒)/u.test(compact)
|
||
|| (/(?:定时任务|自动任务)/u.test(compact) && !queryCue);
|
||
|
||
if (queryCue && !createCue) return true;
|
||
if (/^查/u.test(compact) && /(?:任务|提醒|定时)/u.test(compact) && !/(?:设置|创建)/u.test(compact)) return true;
|
||
return false;
|
||
}
|
||
|
||
export async function formatQueryGuardReply(text, {
|
||
scheduleService,
|
||
scheduledTaskService,
|
||
taskUnifiedService = null,
|
||
userId,
|
||
timezone = 'Asia/Shanghai',
|
||
env = process.env,
|
||
} = {}) {
|
||
const compact = normalizeCompact(text);
|
||
if (/待办/u.test(compact) && scheduleService?.buildTodoDigestText) {
|
||
return scheduleService.buildTodoDigestText({ userId, timezone });
|
||
}
|
||
|
||
if (/(?:定时|自动).{0,8}任务/u.test(compact)) {
|
||
if (taskUnifiedService?.listUserTasks) {
|
||
const tasks = await taskUnifiedService.listUserTasks({ userId, status: 'active', limit: 10, timezone });
|
||
return formatUnifiedTaskListReply(tasks, { timezone });
|
||
}
|
||
if (scheduledTaskService?.listTasks) {
|
||
const tasks = await scheduledTaskService.listTasks({ userId, status: 'active', limit: 10 });
|
||
return formatScheduledTaskListReply(tasks);
|
||
}
|
||
}
|
||
|
||
return '这是查询请求,我不会新建或修改任何提醒/任务。如需设置,请直接说「下午 2 点半提醒我开会」或「每天 6 点帮我做新闻页面」。';
|
||
}
|
||
|
||
function formatScheduledTaskListReply(tasks) {
|
||
if (!tasks?.length) return '你当前没有进行中的定时自动任务。';
|
||
const lines = ['你的定时自动任务:'];
|
||
for (const task of tasks.slice(0, 10)) {
|
||
const when = task.recurrence === 'once'
|
||
? new Date(Number(task.nextRunAt)).toLocaleString('zh-CN', { timeZone: task.timezone || 'Asia/Shanghai', hour12: false })
|
||
: `${String(task.hour).padStart(2, '0')}:${String(task.minute ?? 0).padStart(2, '0')}`;
|
||
lines.push(`- ${task.title}(${task.recurrence} ${when})`);
|
||
}
|
||
return lines.join('\n');
|
||
}
|