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>
115 lines
3.6 KiB
JavaScript
115 lines
3.6 KiB
JavaScript
import { formatIntentActionCard } from './intent-action-card.mjs';
|
|
import { isIntentTransactionEnabled } from './intent-transaction-config.mjs';
|
|
|
|
export function isSideEffectConfirmGateEnabled(env = process.env) {
|
|
return isIntentTransactionEnabled(env);
|
|
}
|
|
|
|
function buildScheduledTaskConfirmCard(args) {
|
|
const title = String(args.title ?? args.taskSpec ?? '').trim() || '定时自动任务';
|
|
const trigger = args.recurrence === 'once'
|
|
? { at: args.runAtLocal ?? null }
|
|
: { hour: args.hour, minute: args.minute ?? 0 };
|
|
const frequency = args.recurrence === 'weekly'
|
|
? '每周自动执行'
|
|
: args.recurrence === 'once'
|
|
? null
|
|
: '每天自动执行';
|
|
return formatIntentActionCard({
|
|
title: title.slice(0, 80),
|
|
layer: 'L2',
|
|
actionLevel: 2,
|
|
trigger,
|
|
actions: ['到点自动执行任务', '推送执行结果到微信'],
|
|
frequency,
|
|
});
|
|
}
|
|
|
|
function buildScheduleItemConfirmCard(args) {
|
|
const title = String(args.title ?? '').trim() || '待办/日程';
|
|
const remindLocal = args.remindLocal ?? args.startLocal ?? null;
|
|
const trigger = remindLocal ? { at: remindLocal } : { hour: null, minute: 0 };
|
|
const actions = args.remindLocal || args.remindAt || args.startLocal || args.startAt
|
|
? ['到点发送微信提醒']
|
|
: ['记录到待办列表'];
|
|
return formatIntentActionCard({
|
|
title: title.slice(0, 80),
|
|
layer: 'L1',
|
|
actionLevel: 1,
|
|
trigger,
|
|
actions,
|
|
});
|
|
}
|
|
|
|
function buildScheduleReminderConfirmCard(args) {
|
|
const trigger = args.remindLocal ? { at: args.remindLocal } : { hour: null, minute: 0 };
|
|
return formatIntentActionCard({
|
|
title: '日程提醒',
|
|
layer: 'L1',
|
|
actionLevel: 1,
|
|
trigger,
|
|
actions: ['到点发送微信提醒'],
|
|
});
|
|
}
|
|
|
|
export async function requireUserConfirmForSideEffectTool({
|
|
userId,
|
|
toolName,
|
|
toolArgs,
|
|
intentDraftService,
|
|
env = process.env,
|
|
layer = 'L2',
|
|
actionLevel = 2,
|
|
title = null,
|
|
cardText = null,
|
|
} = {}) {
|
|
if (!isSideEffectConfirmGateEnabled(env)) {
|
|
return { proceed: true };
|
|
}
|
|
if (!intentDraftService || !userId) {
|
|
return { proceed: true };
|
|
}
|
|
|
|
const safeToolName = String(toolName ?? '').trim();
|
|
const args = { ...(toolArgs ?? {}) };
|
|
const resolvedCardText = cardText
|
|
?? (safeToolName === 'scheduled_task_create'
|
|
? buildScheduledTaskConfirmCard(args)
|
|
: safeToolName === 'schedule_create_item'
|
|
? buildScheduleItemConfirmCard(args)
|
|
: safeToolName === 'schedule_create_reminder'
|
|
? buildScheduleReminderConfirmCard(args)
|
|
: formatIntentActionCard({ title: title ?? '待确认操作', layer, actionLevel }));
|
|
const resolvedTitle = String(title ?? args.title ?? args.taskSpec ?? resolvedCardText.split('\n')[0] ?? '待确认任务').trim();
|
|
|
|
const draft = await intentDraftService.createDraft({
|
|
userId,
|
|
layer,
|
|
draftType: 'agent_tool',
|
|
actionLevel,
|
|
title: resolvedTitle.slice(0, 80),
|
|
payload: {
|
|
toolName: safeToolName,
|
|
toolArgs: args,
|
|
sourceChannel: 'agent',
|
|
sourceMessageId: args.sourceMessageId ?? null,
|
|
sourceText: args.sourceText ?? null,
|
|
},
|
|
cardText: resolvedCardText,
|
|
sourceChannel: 'agent',
|
|
sourceMessageId: args.sourceMessageId ?? null,
|
|
sourceText: args.sourceText ?? null,
|
|
});
|
|
|
|
return {
|
|
proceed: false,
|
|
response: {
|
|
status: 'needs_user_confirmation',
|
|
draftId: draft.id,
|
|
cardText: resolvedCardText,
|
|
instruction:
|
|
'这是需要用户确认的副作用操作。请把 cardText 原样发给用户,并请用户回复「确认」后再写入;在用户确认前不要声称已成功设置。',
|
|
},
|
|
};
|
|
}
|