diff --git a/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/ScheduleTaskArgs.cs b/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/ScheduleTaskArgs.cs index df11160a..af28374a 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/ScheduleTaskArgs.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Crontab/Models/ScheduleTaskArgs.cs @@ -5,6 +5,9 @@ public class ScheduleTaskArgs [JsonPropertyName("cron_expression")] public string Cron { get; set; } = null!; + [JsonPropertyName("less_than_60_seconds")] + public bool LessThan60Seconds { get; set; } = false; + [JsonPropertyName("title")] public string Title { get; set; } = null!; diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Functions/ScheduleTaskFn.cs b/src/Infrastructure/BotSharp.Core.Crontab/Functions/ScheduleTaskFn.cs index 87a1bad6..b538cb3d 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Functions/ScheduleTaskFn.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Functions/ScheduleTaskFn.cs @@ -18,22 +18,37 @@ public class ScheduleTaskFn : IFunctionCallback public async Task Execute(RoleDialogModel message) { var args = JsonSerializer.Deserialize(message.FunctionArgs); + if (args.LessThan60Seconds) + { + message.Content = "Cron expression should not include seconds."; + return false; + } var routing = _services.GetRequiredService(); var user = _services.GetRequiredService(); - var crontabItem = new CrontabItem - { - Title = args.Title, - Description = args.Description, - Cron = args.Cron, - UserId = user.Id, - AgentId = routing.EntryAgentId, - ConversationId = routing.ConversationId, - Tasks = args.Tasks, - }; - var db = _services.GetRequiredService(); - // var ret = db.UpsertCrontabItem(crontabItem); + + if (string.IsNullOrEmpty(args.Cron)) + { + var ret = db.DeleteCrontabItem(routing.ConversationId); + message.Content = $"Task schedule canceled result: {ret}"; + } + else + { + var crontabItem = new CrontabItem + { + Title = args.Title, + Description = args.Description, + Cron = args.Cron, + UserId = user.Id, + AgentId = routing.EntryAgentId, + ConversationId = routing.ConversationId, + Tasks = args.Tasks, + }; + + var ret = db.UpsertCrontabItem(crontabItem); + message.Content = $"Task scheduled result: {ret}"; + } return true; } diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs index e5e68cc0..78b737a0 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabService.cs @@ -15,6 +15,7 @@ ******************************************************************************/ using BotSharp.Abstraction.Repositories; +using BotSharp.Core.Infrastructures; using Microsoft.Extensions.Logging; namespace BotSharp.Core.Crontab.Services; @@ -45,14 +46,9 @@ public class CrontabService : ICrontabService { _logger.LogDebug($"ScheduledTimeArrived {item}"); - var hooks = _services.GetServices(); - foreach(var hook in hooks) - { - await hook.OnCronTriggered(item); - } - /*await HookEmitter.Emit(_services, async hook => + await HookEmitter.Emit(_services, async hook => await hook.OnCronTriggered(item) - );*/ + ); await Task.Delay(1000 * 10); } } diff --git a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs index a7db1220..5a48f58b 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs +++ b/src/Infrastructure/BotSharp.Core.Crontab/Services/CrontabWatcher.cs @@ -48,9 +48,11 @@ public class CrontabWatcher : BackgroundService { try { + // strip seconds from cron expression + item.Cron = string.Join(" ", item.Cron.Split(' ').TakeLast(5)); var schedule = CrontabSchedule.Parse(item.Cron, new CrontabSchedule.ParseOptions { - IncludingSeconds = true // Ensure you account for seconds + IncludingSeconds = false // Ensure you account for seconds }); // Get the current time diff --git a/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-schedule_task.json b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-schedule_task.json index 320f4d71..04131fe1 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-schedule_task.json +++ b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/functions/util-crontab-schedule_task.json @@ -1,12 +1,16 @@ { "name": "util-crontab-schedule_task", - "description": "Set up a scheduled task", + "description": "Set up or cancel a scheduled task", "parameters": { "type": "object", "properties": { "cron_expression": { "type": "string", - "description": "cron expression include seconds" + "description": "cron expression. Set value as empty if user wants to cancel schedule." + }, + "less_than_60_seconds": { + "type": "boolean", + "description": "whether schedule interval is less than 60 seconds" }, "title": { "type": "string", @@ -39,6 +43,6 @@ } } }, - "required": [ "cron_expression", "title", "description", "to_do_list" ] + "required": [ "cron_expression", "include_seconds", "title", "description", "to_do_list" ] } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-crontab-schedule_task.fn.liquid b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-crontab-schedule_task.fn.liquid index 0c132546..17f9cc86 100644 --- a/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-crontab-schedule_task.fn.liquid +++ b/src/Infrastructure/BotSharp.Core.Crontab/data/agents/6745151e-6d46-4a02-8de4-1c4f21c7da95/templates/util-crontab-schedule_task.fn.liquid @@ -1 +1,2 @@ -Call schedule_task if user needs to set up a scheduled task with appropriate programming script and language type. \ No newline at end of file +Call util-crontab-schedule_task if user needs to set up a scheduled task with appropriate programming script and language type. +Set cron_expression as empty if user wants to cancel schedule. \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json index ae99df17..cfd0d779 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json +++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/agent.json @@ -16,7 +16,7 @@ }, { "type": "planner", - "field": "Sequential-Planner" + "field": "Two-Stage-Planner" } ] } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/reasoner.one-step-forward.liquid b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/reasoner.one-step-forward.liquid index dd6fe616..a492175b 100644 --- a/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/reasoner.one-step-forward.liquid +++ b/src/Infrastructure/BotSharp.Core/data/agents/01fcc3e5-9af7-49e6-ad7a-a760bd12dc4a/templates/reasoner.one-step-forward.liquid @@ -1,2 +1,3 @@ Analyze the user's problem. Which prerequisite task needs to be completed? Output the next step of routing instructions. -Check the job responsibilities of the routable Agent and do not transfer to an Agent that exceeds the scope of responsibility. \ No newline at end of file +Check the job responsibilities of the routable Agent and do not transfer to an Agent that exceeds the scope of responsibility. +If the user request may require other tools or services, route to the planner agent. diff --git a/src/Plugins/BotSharp.Plugin.Planner/data/agents/3e75e818-a139-48a8-9e22-4662548c13a3/agent.json b/src/Plugins/BotSharp.Plugin.Planner/data/agents/3e75e818-a139-48a8-9e22-4662548c13a3/agent.json index 59231a43..68a8d48b 100644 --- a/src/Plugins/BotSharp.Plugin.Planner/data/agents/3e75e818-a139-48a8-9e22-4662548c13a3/agent.json +++ b/src/Plugins/BotSharp.Plugin.Planner/data/agents/3e75e818-a139-48a8-9e22-4662548c13a3/agent.json @@ -1,7 +1,7 @@ { "id": "3e75e818-a139-48a8-9e22-4662548c13a3", "name": "Sequential-Planner", - "description": "Plan an ordered plan steps to execute some tasks in a predefined order by the user", + "description": "Plan an execution steps for the user complex task, especially if the tasks are in a predefined order by the user", "type": "planning", "createdDateTime": "2023-08-27T10:39:00Z", "updatedDateTime": "2023-08-27T14:39:00Z", diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Helpers/SqlDriverHelper.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Helpers/SqlDriverHelper.cs index 3049b754..b8576c83 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Helpers/SqlDriverHelper.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Helpers/SqlDriverHelper.cs @@ -5,15 +5,15 @@ internal static class SqlDriverHelper internal static string GetDatabaseType(IServiceProvider services) { var settings = services.GetRequiredService(); - var dbType = "MySQL"; + var dbType = "mysql"; if (!string.IsNullOrWhiteSpace(settings?.SqlServerConnectionString)) { - dbType = "SQL Server"; + dbType = "sqlserver"; } else if (!string.IsNullOrWhiteSpace(settings?.SqlLiteConnectionString)) { - dbType = "SQL Lite"; + dbType = "sqllite"; } return dbType; } diff --git a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverCrontabHook.cs b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverCrontabHook.cs index 7f645cd9..985da6b8 100644 --- a/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverCrontabHook.cs +++ b/src/Plugins/BotSharp.Plugin.SqlDriver/Hooks/SqlDriverCrontabHook.cs @@ -17,38 +17,37 @@ public class SqlDriverCrontabHook : ICrontabHook public async Task OnCronTriggered(CrontabItem item) { - /*var conv = _services.GetRequiredService(); - conv.SetConversationId("abd9df25-2210-4e4d-80d7-48b6a3b905a8", []); + var conv = _services.GetRequiredService(); + conv.SetConversationId(item.ConversationId, []); - if (item.Language == "text") - { - var sidecar = _services.GetService(); - var response = await sidecar.SendMessage(BuiltInAgentId.AIAssistant, item.Description, states: new List()); - return; - } - else if (item.Language != "sql") - { - return; - } + _logger.LogWarning($"Crontab item triggered: {item.Title}. {item.Description}"); - _logger.LogWarning($"Crontab item triggered: {item.Topic}. Run {item.Language}: {item.Script}"); - - var message = new RoleDialogModel(AgentRole.User, $"Run the query") + foreach (var task in item.Tasks) { - FunctionName = "sql_select", - FunctionArgs = JsonSerializer.Serialize(new SqlStatement + if (task.Language == "text") { - Statement = item.Script, - Reason = item.Description - }) - }; - var routing = _services.GetRequiredService(); - routing.Context.Push("ec46f15b-8790-400f-a37f-1e7995b7d6e2"); - await routing.InvokeFunction("sql_select", message); + var sidecar = _services.GetService(); + var response = await sidecar.SendMessage(BuiltInAgentId.AIAssistant, $"{item.ExecutionResult}\r\n{task.Script}", states: new List()); + } + else if (task.Language == "sql") + { + var message = new RoleDialogModel(AgentRole.User, $"Run the query") + { + FunctionName = "sql_select", + FunctionArgs = JsonSerializer.Serialize(new SqlStatement + { + Statement = task.Script, + Reason = item.Description + }) + }; + var routing = _services.GetRequiredService(); + routing.Context.Push(BuiltInAgentId.SqlDriver); + await routing.InvokeFunction("sql_select", message); - item.ConversationId = conv.ConversationId; - item.AgentId = BuiltInAgentId.SqlDriver; - item.UserId = "41021346"; - item.ExecutionResult = message.Content;*/ + item.AgentId = BuiltInAgentId.SqlDriver; + item.UserId = "41021346"; + item.ExecutionResult += message.Content + "\r\n"; + } + } } }