Files
memind/intent-classifier.mjs
T
john d58dc2a251 feat(wechat): add Intent Transaction Layer with unified task schema
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>
2026-08-24 15:59:17 +08:00

85 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { detectQueryGuard } from './intent-query-guard.mjs';
import { parseScheduleIntent, shouldUseScheduleAssistant } from './schedule-intent.mjs';
import {
isScheduledTaskIntent,
parseScheduledTaskIntent,
shouldUseScheduledTaskAutomation,
} from './scheduled-task-intent.mjs';
function detectAmbiguity(text) {
const compact = String(text ?? '').replace(/\s+/g, '');
const notifyCue = /(?:提醒我|设置提醒|设个?提醒|闹钟|叫我)/u.test(compact);
const actCue = /(?:生成|制作|创建|做|执行|推送|发送|整理).{0,12}(?:页面|日报|报告|摘要)/u.test(compact);
if (notifyCue && actCue) return true;
if (notifyCue && /(?:自动|生成)/u.test(compact)) return true;
return false;
}
export function classifyUserIntent(text, { now = Date.now(), timezone = 'Asia/Shanghai' } = {}) {
if (detectQueryGuard(text)) {
return { layer: 'L0', kind: 'query', action: 'answer_only' };
}
const schedTask = parseScheduledTaskIntent(text, { now, timezone });
if (isScheduledTaskIntent(schedTask)) {
if (schedTask.action === 'create_scheduled_task') {
return {
layer: 'L2',
kind: 'scheduled_task',
action: schedTask.action,
detail: schedTask,
clarify: schedTask.needsClarification ?? [],
};
}
return { layer: 'L2', kind: 'manage', action: schedTask.action, detail: schedTask };
}
const sched = parseScheduleIntent(text, { timezone, now });
if (sched.action === 'create_timed_reminder') {
return {
layer: 'L1',
kind: 'timed_reminder',
action: sched.action,
detail: sched,
clarify: sched.needsClarification ?? [],
};
}
if (['create_todo', 'create_daily_todo_digest', 'create_balance_alert'].includes(sched.action)) {
return {
layer: 'L1',
kind: sched.action,
action: sched.action,
detail: sched,
clarify: sched.needsClarification ?? [],
};
}
if (sched.action === 'query_schedule') {
return { layer: 'L0', kind: 'query', action: sched.action, detail: sched };
}
if (detectAmbiguity(text)) {
return { layer: 'ambiguous', kind: 'clarify', action: 'clarify_notify_vs_act' };
}
if (shouldUseScheduledTaskAutomation(text)) {
return { layer: 'L2', kind: 'scheduled_task', action: 'agent_automation', detail: schedTask };
}
if (shouldUseScheduleAssistant(text)) {
const multiTime = (String(text).match(/[0-9零一二两三四五六七八九十]{1,3}(?:点|:|)/gu) ?? []).length > 1;
return { layer: multiTime ? 'L3' : 'L1', kind: 'agent_schedule', action: 'agent_schedule' };
}
return { layer: null, kind: 'none', action: 'none' };
}
export function inferActionLevel(classification, text = '') {
const { layer, kind, detail } = classification;
if (layer === 'L0' || layer === null) return 0;
if (layer === 'ambiguous') return 2;
if (/(?:客户|报价|群发|发邮件)/u.test(text)) return 3;
if (layer === 'L2') return 2;
if (kind === 'create_balance_alert') return 2;
if (detail?.recurrence === 'daily' || /(?:每天|每日)/u.test(text)) return 2;
return 1;
}