package vip.mate.tool.builtin; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.tool.annotation.Tool; import org.springframework.ai.tool.annotation.ToolParam; import org.springframework.stereotype.Component; import vip.mate.cron.model.CronJobDTO; import vip.mate.cron.service.CronJobService; import java.util.List; /** * Built-in tool: scheduled task (cron job) management via chat. *
* Allows agents to create, list, toggle, and delete cron jobs through natural language.
* The agent_id is automatically bound to the current agent. LLM generates cron expressions
* from natural language (e.g. "every day at 9am" → "0 9 * * *").
*
* @author MateClaw Team
* @see vip.mate.cron.service.CronJobService
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class CronJobTool {
private final CronJobService cronJobService;
@vip.mate.tool.ConcurrencyUnsafe("cron job creation persists to mate_cron_job; concurrent creates can race on name")
@Tool(description = "Create a scheduled task (cron job). The task will run automatically at the specified time "
+ "and send the trigger message to the current agent. Use 5-field cron expressions: minute hour day month weekday. "
+ "Examples: '0 9 * * *' = daily at 9am, '0 9 * * 1-5' = weekdays at 9am, '*/30 * * * *' = every 30 minutes.")
public String create_cron_job(
@ToolParam(description = "Task name, e.g. 'Daily AI News Summary'") String name,
@ToolParam(description = "5-field cron expression: minute hour day month weekday") String cronExpression,
@ToolParam(description = "Message to send when the task triggers, e.g. 'Search for the latest AI news and summarize'") String triggerMessage,
@ToolParam(description = "Timezone, default Asia/Shanghai. Examples: UTC, America/New_York", required = false) String timezone) {
try {
// Resolve current agent ID from conversation context
String conversationId = ToolExecutionContext.conversationId();
Long agentId = resolveAgentId(conversationId);
CronJobDTO dto = new CronJobDTO();
dto.setName(name);
dto.setCronExpression(cronExpression);
dto.setTriggerMessage(triggerMessage);
dto.setTimezone(timezone != null && !timezone.isBlank() ? timezone : "Asia/Shanghai");
dto.setAgentId(agentId);
dto.setTaskType("text");
dto.setEnabled(true);
CronJobDTO created = cronJobService.create(dto);
JSONObject result = new JSONObject();
result.set("success", true);
result.set("jobId", created.getId());
result.set("name", created.getName());
result.set("cronExpression", created.getCronExpression());
result.set("timezone", created.getTimezone());
result.set("nextRunTime", created.getNextRunTime() != null ? created.getNextRunTime().toString() : "");
result.set("enabled", created.getEnabled());
return JSONUtil.toJsonPrettyStr(result);
} catch (Exception e) {
log.error("[CronJobTool] create failed: {}", e.getMessage());
return errorResult("Failed to create cron job: " + e.getMessage());
}
}
@Tool(description = "List all scheduled tasks (cron jobs) for the current agent. "
+ "Returns task name, cron expression, next run time, enabled status, and last run time.")
public String list_cron_jobs() {
try {
List