e13df82021
Memind CI / Test, build, and release guards (push) Failing after 14m19s
Stop ITL regex from intercepting new messages before Agent execution; move scheduled task and schedule write confirmation to MCP tool calls with draft commit on 确认. Co-authored-by: Cursor <cursoragent@cursor.com>
160 lines
5.3 KiB
JavaScript
160 lines
5.3 KiB
JavaScript
import { commitAgentSideEffectTool } from './agent-side-effect-tools.mjs';
|
|
import { resolveScheduleTimestamp } from './schedule-time.mjs';
|
|
import { buildScheduledTaskCreatePayload } from './scheduled-task-intent.mjs';
|
|
import { isUnifiedTasksEnabled } from './task-unified-config.mjs';
|
|
|
|
async function maybeSyncUnifiedTask({
|
|
taskUnifiedService,
|
|
userId,
|
|
kind,
|
|
committed,
|
|
env,
|
|
}) {
|
|
if (!isUnifiedTasksEnabled(env) || !taskUnifiedService) return null;
|
|
try {
|
|
return await taskUnifiedService.syncFromCommit({ userId, kind, committed });
|
|
} catch (err) {
|
|
console.warn?.(
|
|
'[intent-transaction-commit] unified task sync failed open:',
|
|
err instanceof Error ? err.message : err,
|
|
);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function commitIntentDraft({
|
|
draft,
|
|
userId,
|
|
scheduleService,
|
|
scheduledTaskService,
|
|
taskUnifiedService = null,
|
|
timezone = 'Asia/Shanghai',
|
|
env = process.env,
|
|
}) {
|
|
if (!draft || draft.status !== 'draft') throw new Error('草稿不可提交');
|
|
const payload = draft.payload ?? {};
|
|
const kind = draft.draftType;
|
|
|
|
if (kind === 'timed_reminder') {
|
|
if (!scheduleService) throw new Error('scheduleService 不可用');
|
|
const remindAt = resolveScheduleTimestamp({
|
|
localString: payload.remindLocal,
|
|
timezone,
|
|
fieldName: '提醒时间',
|
|
});
|
|
const item = await scheduleService.createItem({
|
|
userId,
|
|
kind: 'event',
|
|
title: payload.title ?? draft.title,
|
|
startAt: remindAt,
|
|
timezone,
|
|
sourceChannel: payload.sourceChannel ?? 'wechat',
|
|
sourceMessageId: payload.sourceMessageId ?? draft.sourceMessageId,
|
|
sourceText: payload.sourceText ?? draft.sourceText,
|
|
metadata: {
|
|
source: 'intent_transaction_layer',
|
|
...(payload.recurrence === 'daily'
|
|
? {
|
|
recurrence: 'daily',
|
|
dailyHour: Number(payload.hour),
|
|
dailyMinute: Number(payload.minute ?? 0),
|
|
}
|
|
: {}),
|
|
},
|
|
});
|
|
const reminder = await scheduleService.createReminder({
|
|
userId,
|
|
itemId: item.id,
|
|
remindAt,
|
|
channel: 'wechat',
|
|
});
|
|
const committed = { kind, item, reminder };
|
|
await maybeSyncUnifiedTask({ taskUnifiedService, userId, kind, committed, env });
|
|
return committed;
|
|
}
|
|
|
|
if (kind === 'create_todo') {
|
|
if (!scheduleService) throw new Error('scheduleService 不可用');
|
|
const item = await scheduleService.createItem({
|
|
userId,
|
|
kind: 'task',
|
|
title: payload.title ?? draft.title,
|
|
timezone,
|
|
sourceChannel: payload.sourceChannel ?? 'wechat',
|
|
sourceMessageId: payload.sourceMessageId ?? draft.sourceMessageId,
|
|
sourceText: payload.sourceText ?? draft.sourceText,
|
|
metadata: { source: 'intent_transaction_layer' },
|
|
});
|
|
const committed = { kind, item };
|
|
await maybeSyncUnifiedTask({ taskUnifiedService, userId, kind, committed, env });
|
|
return committed;
|
|
}
|
|
|
|
if (kind === 'create_daily_todo_digest') {
|
|
if (!scheduleService) throw new Error('scheduleService 不可用');
|
|
const subscription = await scheduleService.createDailyTodoDigest({
|
|
userId,
|
|
hour: payload.hour,
|
|
minute: payload.minute ?? 0,
|
|
timezone,
|
|
channel: 'wechat',
|
|
sourceChannel: payload.sourceChannel ?? 'wechat',
|
|
sourceMessageId: payload.sourceMessageId ?? draft.sourceMessageId,
|
|
sourceText: payload.sourceText ?? draft.sourceText,
|
|
});
|
|
const committed = { kind, subscription };
|
|
await maybeSyncUnifiedTask({ taskUnifiedService, userId, kind, committed, env });
|
|
return committed;
|
|
}
|
|
|
|
if (kind === 'create_balance_alert') {
|
|
if (!scheduleService) throw new Error('scheduleService 不可用');
|
|
const subscription = await scheduleService.createBalanceLowAlert({
|
|
userId,
|
|
thresholdCents: payload.thresholdCents,
|
|
channel: 'wechat',
|
|
sourceChannel: payload.sourceChannel ?? 'wechat',
|
|
sourceMessageId: payload.sourceMessageId ?? draft.sourceMessageId,
|
|
sourceText: payload.sourceText ?? draft.sourceText,
|
|
});
|
|
const committed = { kind, subscription };
|
|
await maybeSyncUnifiedTask({ taskUnifiedService, userId, kind, committed, env });
|
|
return committed;
|
|
}
|
|
|
|
if (kind === 'scheduled_task') {
|
|
if (!scheduledTaskService) throw new Error('scheduledTaskService 不可用');
|
|
const createPayload = payload.createPayload ?? buildScheduledTaskCreatePayload(payload.intentDetail ?? payload, {
|
|
userId,
|
|
sourceChannel: 'wechat',
|
|
sourceMessageId: payload.sourceMessageId ?? draft.sourceMessageId,
|
|
sourceText: payload.sourceText ?? draft.sourceText,
|
|
timezone,
|
|
});
|
|
const task = await scheduledTaskService.createTask(createPayload);
|
|
const committed = { kind, task };
|
|
await maybeSyncUnifiedTask({ taskUnifiedService, userId, kind, committed, env });
|
|
return committed;
|
|
}
|
|
|
|
if (kind === 'agent_tool') {
|
|
const committed = await commitAgentSideEffectTool(payload.toolName, payload.toolArgs, {
|
|
userId,
|
|
scheduleService,
|
|
scheduledTaskService,
|
|
timezone,
|
|
env,
|
|
});
|
|
await maybeSyncUnifiedTask({
|
|
taskUnifiedService,
|
|
userId,
|
|
kind: committed.kind === 'scheduled_task' ? 'scheduled_task' : kind,
|
|
committed,
|
|
env,
|
|
});
|
|
return committed;
|
|
}
|
|
|
|
throw new Error(`不支持的草稿类型:${kind}`);
|
|
}
|