Files
memind/agent-side-effect-tools.mjs
T
john a1a921eba6 fix(wechat): route scheduled task cancel and spec updates through Goose MCP
Pass cancel requests to Goose like create instead of inbound title matching,
and add scheduled_task_update_spec so format or execution constraints update
taskSpec without triggering page delivery guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 09:47:39 +08:00

165 lines
5.0 KiB
JavaScript

import { resolveScheduleTimestamp } from './schedule-time.mjs';
import { shouldAutoCreateReminderAtStart } from './schedule-service.mjs';
import {
isScheduledTaskWorkerEnabled,
scheduledTaskWorkerDisabledMessage,
} from './scheduled-task-worker-config.mjs';
export async function executeScheduledTaskCreateTool(args, {
userId,
scheduledTaskService,
timezone = 'Asia/Shanghai',
env = process.env,
} = {}) {
if (!scheduledTaskService) throw new Error('scheduledTaskService 不可用');
const task = await scheduledTaskService.createTask({
userId,
title: args.title ?? null,
taskSpec: args.taskSpec,
recurrence: args.recurrence ?? 'daily',
runAtLocal: args.runAtLocal ?? null,
hour: args.hour ?? null,
minute: args.minute ?? 0,
weekday: args.weekday ?? null,
timezone: args.timezone ?? timezone,
notifyChannel: args.notifyChannel ?? 'both',
sourceChannel: args.sourceChannel ?? 'agent',
sourceMessageId: args.sourceMessageId ?? null,
sourceText: args.sourceText ?? null,
});
const workerWarning = isScheduledTaskWorkerEnabled(env)
? null
: scheduledTaskWorkerDisabledMessage(env);
return workerWarning ? { ...task, workerWarning } : task;
}
export async function executeScheduledTaskUpdateSpecTool(args, {
userId,
scheduledTaskService,
} = {}) {
if (!scheduledTaskService) throw new Error('scheduledTaskService 不可用');
return scheduledTaskService.updateTaskSpec({
userId,
taskId: args.taskId,
taskSpec: args.taskSpec ?? null,
title: args.title ?? null,
mergeTaskSpec: Boolean(args.mergeTaskSpec),
});
}
export async function executeScheduleCreateItemTool(args, {
userId,
scheduleService,
timezone = 'Asia/Shanghai',
} = {}) {
if (!scheduleService) throw new Error('scheduleService 不可用');
const tz = args.timezone ?? timezone;
const startAt = resolveScheduleTimestamp({
epochMs: args.startAt,
localString: args.startLocal,
timezone: tz,
fieldName: '开始时间',
});
const endAt = resolveScheduleTimestamp({
epochMs: args.endAt,
localString: args.endLocal,
timezone: tz,
fieldName: '结束时间',
});
const dueAt = resolveScheduleTimestamp({
epochMs: args.dueAt,
localString: args.dueLocal,
timezone: tz,
fieldName: '截止时间',
});
const item = await scheduleService.createItem({
userId,
kind: args.kind,
title: args.title,
description: args.description ?? null,
startAt,
endAt,
dueAt,
allDay: Boolean(args.allDay),
timezone: tz,
location: args.location ?? null,
sourceChannel: args.sourceChannel ?? 'agent',
sourceMessageId: args.sourceMessageId ?? null,
sourceText: args.sourceText ?? null,
metadata: args.metadata ?? { source: 'agent_tool' },
});
let remindAt = resolveScheduleTimestamp({
epochMs: args.remindAt,
localString: args.remindLocal,
timezone: tz,
fieldName: '提醒时间',
});
if (
remindAt == null
&& shouldAutoCreateReminderAtStart({
title: args.title,
description: args.description,
startAt,
noReminder: Boolean(args.noReminder),
})
) {
remindAt = startAt;
}
if (remindAt != null) {
const reminder = await scheduleService.createReminder({
userId,
itemId: item.id,
remindAt,
offsetMinutes: args.offsetMinutes ?? null,
channel: args.channel ?? 'wechat',
});
return { item, reminder };
}
return { item };
}
export async function executeScheduleCreateReminderTool(args, {
userId,
scheduleService,
timezone = 'Asia/Shanghai',
} = {}) {
if (!scheduleService) throw new Error('scheduleService 不可用');
const tz = args.timezone ?? timezone;
const remindAt = resolveScheduleTimestamp({
epochMs: args.remindAt,
localString: args.remindLocal,
timezone: tz,
fieldName: '提醒时间',
});
if (remindAt == null) throw new Error('缺少提醒时间 remindLocal 或 remindAt');
const reminder = await scheduleService.createReminder({
userId,
itemId: args.itemId,
remindAt,
offsetMinutes: args.offsetMinutes ?? null,
channel: args.channel ?? 'wechat',
});
return reminder;
}
export async function commitAgentSideEffectTool(toolName, toolArgs, services) {
const name = String(toolName ?? '').trim();
if (name === 'scheduled_task_create') {
const task = await executeScheduledTaskCreateTool(toolArgs, services);
return { kind: 'scheduled_task', task };
}
if (name === 'scheduled_task_update_spec') {
const task = await executeScheduledTaskUpdateSpecTool(toolArgs, services);
return { kind: 'scheduled_task', task, updated: true };
}
if (name === 'schedule_create_item') {
const result = await executeScheduleCreateItemTool(toolArgs, services);
return { kind: 'schedule_item', ...result };
}
if (name === 'schedule_create_reminder') {
const reminder = await executeScheduleCreateReminderTool(toolArgs, services);
return { kind: 'schedule_reminder', reminder };
}
throw new Error(`不支持的 agent 副作用工具:${name}`);
}