Merge pull request #287 from iceljc/features/add-agent-task-mongo
Features/add agent task mongo
This commit is contained in:
commit
620bd02d37
|
|
@ -18,3 +18,12 @@ public enum AgentField
|
|||
Sample,
|
||||
LlmConfig
|
||||
}
|
||||
|
||||
public enum AgentTaskField
|
||||
{
|
||||
All = 1,
|
||||
Name,
|
||||
Description,
|
||||
Enabled,
|
||||
Content
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,5 @@ public class AgentTaskFilter
|
|||
{
|
||||
public Pagination Pager { get; set; } = new Pagination();
|
||||
public string? AgentId { get; set; }
|
||||
public bool? Enabled { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using BotSharp.Abstraction.Plugins.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Repositories;
|
||||
|
|
@ -34,6 +35,14 @@ public interface IBotSharpRepository
|
|||
string GetAgentTemplate(string agentId, string templateName);
|
||||
#endregion
|
||||
|
||||
#region Agent Task
|
||||
PagedItems<AgentTask> GetAgentTasks(AgentTaskFilter filter);
|
||||
AgentTask? GetAgentTask(string agentId, string taskId);
|
||||
void InsertAgentTask(AgentTask task);
|
||||
void UpdateAgentTask(AgentTask task, AgentTaskField field);
|
||||
bool DeleteAgentTask(string agentId, string taskId);
|
||||
#endregion
|
||||
|
||||
#region Conversation
|
||||
void CreateNewConversation(Conversation conversation);
|
||||
bool DeleteConversation(string conversationId);
|
||||
|
|
@ -49,9 +58,7 @@ public interface IBotSharpRepository
|
|||
List<Conversation> GetLastConversations();
|
||||
bool TruncateConversation(string conversationId, string messageId);
|
||||
#endregion
|
||||
#region Statistics
|
||||
void IncrementConversationCount();
|
||||
#endregion
|
||||
|
||||
#region Execution Log
|
||||
void AddExecutionLogs(string conversationId, List<string> logs);
|
||||
List<string> GetExecutionLogs(string conversationId);
|
||||
|
|
@ -60,4 +67,8 @@ public interface IBotSharpRepository
|
|||
#region LLM Completion Log
|
||||
void SaveLlmCompletionLog(LlmCompletionLog log);
|
||||
#endregion
|
||||
|
||||
#region Statistics
|
||||
void IncrementConversationCount();
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,12 @@ namespace BotSharp.Abstraction.Tasks;
|
|||
public interface IAgentTaskService
|
||||
{
|
||||
Task<PagedItems<AgentTask>> GetTasks(AgentTaskFilter filter);
|
||||
|
||||
Task<AgentTask?> GetTask(string agentId, string taskId);
|
||||
|
||||
Task CreateTask(AgentTask task);
|
||||
|
||||
Task UpdateTask(AgentTask task, AgentTaskField field);
|
||||
|
||||
Task<bool> DeleteTask(string agentId, string taskId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,17 @@ public class AgentTask
|
|||
public DateTime CreatedDateTime { get; set; }
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public string AgentId { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.Always)]
|
||||
public Agent Agent { get; set; }
|
||||
|
||||
public AgentTask()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AgentTask(string id, string name, string? description = null)
|
||||
{
|
||||
Id = id;
|
||||
|
|
|
|||
|
|
@ -13,5 +13,5 @@ public class Pagination
|
|||
public class PagedItems<T>
|
||||
{
|
||||
public int Count { get; set; }
|
||||
public IEnumerable<T> Items { get; set; }
|
||||
public IEnumerable<T> Items { get; set; } = new List<T>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using BotSharp.Abstraction.Plugins.Models;
|
|||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Repositories.Models;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
|
|
@ -119,6 +120,32 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region Agent Task
|
||||
public PagedItems<AgentTask> GetAgentTasks(AgentTaskFilter filter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public AgentTask? GetAgentTask(string agentId, string taskId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void InsertAgentTask(AgentTask task)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void UpdateAgentTask(AgentTask task, AgentTaskField field)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Conversation
|
||||
public void CreateNewConversation(Conversation conversation)
|
||||
|
|
@ -184,13 +211,7 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
#region Stats
|
||||
public void IncrementConversationCount()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region User
|
||||
public User? GetUserByEmail(string email)
|
||||
=> throw new NotImplementedException();
|
||||
|
|
@ -205,7 +226,6 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
=> throw new NotImplementedException();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Execution Log
|
||||
public void AddExecutionLogs(string conversationId, List<string> logs)
|
||||
{
|
||||
|
|
@ -224,4 +244,11 @@ public class BotSharpDbContext : Database, IBotSharpRepository
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Stats
|
||||
public void IncrementConversationCount()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Evaluations.Settings;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Repository
|
||||
|
|
@ -326,12 +326,11 @@ namespace BotSharp.Core.Repository
|
|||
var functions = FetchFunctions(dir);
|
||||
var samples = FetchSamples(dir);
|
||||
var templates = FetchTemplates(dir);
|
||||
var tasks = FetchTasks(dir);
|
||||
var responses = FetchResponses(dir);
|
||||
return record.SetInstruction(instruction)
|
||||
.SetFunctions(functions)
|
||||
.SetSamples(samples)
|
||||
.SetTemplates(templates)
|
||||
.SetSamples(samples)
|
||||
.SetResponses(responses);
|
||||
}
|
||||
|
||||
|
|
@ -406,6 +405,7 @@ namespace BotSharp.Core.Repository
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public void BulkInsertAgents(List<Agent> agents)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
public partial class FileRepository
|
||||
{
|
||||
#region Task
|
||||
public PagedItems<AgentTask> GetAgentTasks(AgentTaskFilter filter)
|
||||
{
|
||||
var tasks = new List<AgentTask>();
|
||||
var pager = filter.Pager ?? new Pagination();
|
||||
var skipCount = 0;
|
||||
var takeCount = 0;
|
||||
var totalCount = 0;
|
||||
var matched = true;
|
||||
|
||||
var dir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir);
|
||||
if (!Directory.Exists(dir)) return new PagedItems<AgentTask>();
|
||||
|
||||
foreach (var agentDir in Directory.GetDirectories(dir))
|
||||
{
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir)) continue;
|
||||
|
||||
var agentId = agentDir.Split(Path.DirectorySeparatorChar).Last();
|
||||
|
||||
matched = true;
|
||||
if (filter?.AgentId != null)
|
||||
{
|
||||
matched = agentId == filter.AgentId;
|
||||
}
|
||||
|
||||
if (!matched) continue;
|
||||
|
||||
var curTasks = new List<AgentTask>();
|
||||
foreach (var taskFile in Directory.GetFiles(taskDir))
|
||||
{
|
||||
var task = ParseAgentTask(taskFile);
|
||||
if (task == null) continue;
|
||||
|
||||
matched = true;
|
||||
if (filter?.Enabled != null)
|
||||
{
|
||||
matched = matched && task.Enabled == filter.Enabled;
|
||||
}
|
||||
|
||||
if (!matched) continue;
|
||||
|
||||
totalCount++;
|
||||
if (takeCount >= pager.Size) continue;
|
||||
|
||||
if (skipCount < pager.Offset)
|
||||
{
|
||||
skipCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
curTasks.Add(task);
|
||||
takeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (curTasks.IsNullOrEmpty()) continue;
|
||||
|
||||
var agent = ParseAgent(agentDir);
|
||||
curTasks.ForEach(t =>
|
||||
{
|
||||
t.AgentId = agentId;
|
||||
t.Agent = agent;
|
||||
});
|
||||
tasks.AddRange(curTasks);
|
||||
}
|
||||
|
||||
return new PagedItems<AgentTask>
|
||||
{
|
||||
Items = tasks,
|
||||
Count = totalCount
|
||||
};
|
||||
}
|
||||
|
||||
public AgentTask? GetAgentTask(string agentId, string taskId)
|
||||
{
|
||||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||
if (!Directory.Exists(agentDir)) return null;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir)) return null;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, taskId);
|
||||
if (taskFile == null) return null;
|
||||
|
||||
var task = ParseAgentTask(taskFile);
|
||||
if (task == null) return null;
|
||||
|
||||
var agent = ParseAgent(agentDir);
|
||||
task.AgentId = agentId;
|
||||
task.Agent = agent;
|
||||
return task;
|
||||
}
|
||||
|
||||
public void InsertAgentTask(AgentTask task)
|
||||
{
|
||||
if (task == null || string.IsNullOrEmpty(task.AgentId)) return;
|
||||
|
||||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, task.AgentId);
|
||||
if (!Directory.Exists(agentDir)) return;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir))
|
||||
{
|
||||
Directory.CreateDirectory(taskDir);
|
||||
}
|
||||
|
||||
var fileName = $"{Guid.NewGuid()}.liquid";
|
||||
var taskFile = Path.Combine(taskDir, fileName);
|
||||
|
||||
var model = new AgentTaskFileModel
|
||||
{
|
||||
Name = task.Name,
|
||||
Description = task.Description,
|
||||
Enabled = task.Enabled,
|
||||
CreatedDateTime = DateTime.UtcNow,
|
||||
UpdatedDateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
var fileContent = BuildAgentTaskFileContent(model, task.Content);
|
||||
File.WriteAllText(taskFile, fileContent);
|
||||
}
|
||||
|
||||
public void UpdateAgentTask(AgentTask task, AgentTaskField field)
|
||||
{
|
||||
if (task == null || string.IsNullOrEmpty(task.Id)) return;
|
||||
|
||||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, task.AgentId);
|
||||
if (!Directory.Exists(agentDir)) return;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir)) return;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, task.Id);
|
||||
if (string.IsNullOrEmpty(taskFile)) return;
|
||||
|
||||
var parsedTask = ParseAgentTask(taskFile);
|
||||
if (parsedTask == null) return;
|
||||
|
||||
var model = new AgentTaskFileModel
|
||||
{
|
||||
Name = parsedTask.Name,
|
||||
Description = parsedTask.Description,
|
||||
Enabled = parsedTask.Enabled,
|
||||
CreatedDateTime = parsedTask.CreatedDateTime,
|
||||
UpdatedDateTime = DateTime.UtcNow
|
||||
};
|
||||
var content = parsedTask.Content;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case AgentTaskField.Name:
|
||||
model.Name = task.Name;
|
||||
break;
|
||||
case AgentTaskField.Description:
|
||||
model.Description = task.Description;
|
||||
break;
|
||||
case AgentTaskField.Enabled:
|
||||
model.Enabled = task.Enabled;
|
||||
break;
|
||||
case AgentTaskField.Content:
|
||||
content = task.Content;
|
||||
break;
|
||||
case AgentTaskField.All:
|
||||
model.Name = task.Name;
|
||||
model.Description = task.Description;
|
||||
model.Enabled = task.Enabled;
|
||||
content = task.Content;
|
||||
break;
|
||||
}
|
||||
|
||||
var fileContent = BuildAgentTaskFileContent(model, content);
|
||||
File.WriteAllText(taskFile, fileContent);
|
||||
}
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
{
|
||||
var agentDir = Path.Combine(_dbSettings.FileRepository, _agentSettings.DataDir, agentId);
|
||||
if (!Directory.Exists(agentDir)) return false;
|
||||
|
||||
var taskDir = Path.Combine(agentDir, "tasks");
|
||||
if (!Directory.Exists(taskDir)) return false;
|
||||
|
||||
var taskFile = FindTaskFileById(taskDir, taskId);
|
||||
if (string.IsNullOrWhiteSpace(taskFile)) return false;
|
||||
|
||||
File.Delete(taskFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
private string? FindTaskFileById(string taskDir, string taskId)
|
||||
{
|
||||
if (!Directory.Exists(taskDir) || string.IsNullOrEmpty(taskId)) return null;
|
||||
|
||||
var taskFile = Directory.GetFiles(taskDir).FirstOrDefault(file =>
|
||||
{
|
||||
var fileName = file.Split(Path.DirectorySeparatorChar).Last();
|
||||
var id = fileName.Split('.').First();
|
||||
return id.IsEqualTo(taskId);
|
||||
});
|
||||
|
||||
return taskFile;
|
||||
}
|
||||
|
||||
private string BuildAgentTaskFileContent(AgentTaskFileModel fileModel, string taskContent)
|
||||
{
|
||||
return $"{AGENT_TASK_PREFIX}\n{JsonSerializer.Serialize(fileModel, _options)}\n{AGENT_TASK_SUFFIX}\n\n{taskContent}";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class AgentTaskFileModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
}
|
||||
|
|
@ -35,9 +35,9 @@ namespace BotSharp.Core.Repository
|
|||
{
|
||||
Key = x.Key,
|
||||
Values = new List<StateValue>
|
||||
{
|
||||
new StateValue { Data = x.Value, UpdateTime = DateTime.UtcNow }
|
||||
}
|
||||
{
|
||||
new StateValue { Data = x.Value, UpdateTime = DateTime.UtcNow }
|
||||
}
|
||||
}).ToList();
|
||||
File.WriteAllText(stateFile, JsonSerializer.Serialize(initialStates, _options));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ public partial class FileRepository : IBotSharpRepository
|
|||
private const string STATE_FILE = "state.json";
|
||||
private const string EXECUTION_LOG_FILE = "execution.log";
|
||||
private const string PLUGIN_CONFIG_FILE = "config.json";
|
||||
private const string AGENT_TASK_PREFIX = "#metadata";
|
||||
private const string AGENT_TASK_SUFFIX = "/metadata";
|
||||
|
||||
public FileRepository(
|
||||
IServiceProvider services,
|
||||
|
|
@ -116,9 +118,8 @@ public partial class FileRepository : IBotSharpRepository
|
|||
if (agent != null)
|
||||
{
|
||||
agent = agent.SetInstruction(FetchInstruction(d))
|
||||
.SetTemplates(FetchTemplates(d))
|
||||
.SetTasks(FetchTasks(d))
|
||||
.SetFunctions(FetchFunctions(d))
|
||||
.SetTemplates(FetchTemplates(d))
|
||||
.SetResponses(FetchResponses(d))
|
||||
.SetSamples(FetchSamples(d));
|
||||
_agents.Add(agent);
|
||||
|
|
@ -236,19 +237,10 @@ public partial class FileRepository : IBotSharpRepository
|
|||
|
||||
foreach (var file in Directory.GetFiles(taskDir))
|
||||
{
|
||||
var fileName = file.Split(Path.DirectorySeparatorChar).Last();
|
||||
var id = fileName.Split('.').First();
|
||||
var data = File.ReadAllText(file);
|
||||
var metadata = Regex.Match(data, @"#metadata.+/metadata", RegexOptions.Singleline);
|
||||
var task = ParseAgentTask(file);
|
||||
if (task == null) continue;
|
||||
|
||||
if (metadata.Success)
|
||||
{
|
||||
var task = metadata.Value.JsonContent<AgentTask>();
|
||||
task.Id = id;
|
||||
var content = Regex.Match(data, @"/metadata.+", RegexOptions.Singleline).Value;
|
||||
task.Content = content.Substring(9).Trim();
|
||||
tasks.Add(task);
|
||||
}
|
||||
tasks.Add(task);
|
||||
}
|
||||
|
||||
return tasks;
|
||||
|
|
@ -273,6 +265,51 @@ public partial class FileRepository : IBotSharpRepository
|
|||
return responses;
|
||||
}
|
||||
|
||||
private Agent? ParseAgent(string agentDir)
|
||||
{
|
||||
if (string.IsNullOrEmpty(agentDir)) return null;
|
||||
|
||||
var agentJson = File.ReadAllText(Path.Combine(agentDir, AGENT_FILE));
|
||||
if (string.IsNullOrEmpty(agentJson)) return null;
|
||||
|
||||
var agent = JsonSerializer.Deserialize<Agent>(agentJson, _options);
|
||||
if (agent == null) return null;
|
||||
|
||||
var instruction = FetchInstruction(agentDir);
|
||||
var functions = FetchFunctions(agentDir);
|
||||
var samples = FetchSamples(agentDir);
|
||||
var templates = FetchTemplates(agentDir);
|
||||
var responses = FetchResponses(agentDir);
|
||||
|
||||
return agent.SetInstruction(instruction)
|
||||
.SetFunctions(functions)
|
||||
.SetTemplates(templates)
|
||||
.SetSamples(samples)
|
||||
.SetResponses(responses);
|
||||
}
|
||||
|
||||
private AgentTask? ParseAgentTask(string taskFile)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(taskFile)) return null;
|
||||
|
||||
var fileName = taskFile.Split(Path.DirectorySeparatorChar).Last();
|
||||
var id = fileName.Split('.').First();
|
||||
var data = File.ReadAllText(taskFile);
|
||||
var pattern = $@"{AGENT_TASK_PREFIX}.+{AGENT_TASK_SUFFIX}";
|
||||
var metaData = Regex.Match(data, pattern, RegexOptions.Singleline);
|
||||
|
||||
if (!metaData.Success) return null;
|
||||
|
||||
var task = metaData.Value.JsonContent<AgentTask>();
|
||||
if (task == null) return null;
|
||||
|
||||
task.Id = id;
|
||||
pattern = $@"{AGENT_TASK_SUFFIX}.+";
|
||||
var content = Regex.Match(data, pattern, RegexOptions.Singleline).Value;
|
||||
task.Content = content.Substring(AGENT_TASK_SUFFIX.Length).Trim();
|
||||
return task;
|
||||
}
|
||||
|
||||
private string[] ParseFileNameByPath(string path, string separator = ".")
|
||||
{
|
||||
var name = path.Split(Path.DirectorySeparatorChar).Last();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Repositories;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
|
@ -14,23 +15,36 @@ public class AgentTaskService : IAgentTaskService
|
|||
|
||||
public async Task<PagedItems<AgentTask>> GetTasks(AgentTaskFilter filter)
|
||||
{
|
||||
var agentService = _services.GetRequiredService<IAgentService>();
|
||||
var agents = await agentService.GetAgents(new AgentFilter());
|
||||
var tasks = new List<AgentTask>();
|
||||
foreach (var agent in agents.Items)
|
||||
{
|
||||
if (filter.AgentId != null && filter.AgentId != agent.Id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
agent.Tasks.ForEach(x => x.Agent = agent);
|
||||
tasks.AddRange(agent.Tasks);
|
||||
}
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var pagedTasks = db.GetAgentTasks(filter);
|
||||
return await Task.FromResult(pagedTasks);
|
||||
}
|
||||
|
||||
return new PagedItems<AgentTask>
|
||||
{
|
||||
Items = tasks.Skip(filter.Pager.Offset).Take(filter.Pager.Size),
|
||||
Count = tasks.Count,
|
||||
};
|
||||
public async Task<AgentTask?> GetTask(string agentId, string taskId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var task = db.GetAgentTask(agentId, taskId);
|
||||
return await Task.FromResult(task);
|
||||
}
|
||||
|
||||
public async Task CreateTask(AgentTask task)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.InsertAgentTask(task);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task UpdateTask(AgentTask task, AgentTaskField field)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
db.UpdateAgentTask(task, field);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteTask(string agentId, string taskId)
|
||||
{
|
||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||
var isDeleted = db.DeleteAgentTask(agentId, taskId);
|
||||
return await Task.FromResult(isDeleted);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Tasks;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
@ -8,30 +6,64 @@ namespace BotSharp.OpenAPI.Controllers;
|
|||
[ApiController]
|
||||
public class AgentTaskController : ControllerBase
|
||||
{
|
||||
private readonly IAgentService _agentService;
|
||||
private readonly IAgentTaskService _agentTaskService;
|
||||
private readonly IServiceProvider _services;
|
||||
|
||||
public AgentTaskController(IAgentService agentService, IServiceProvider services)
|
||||
public AgentTaskController(IAgentTaskService agentTaskService, IServiceProvider services)
|
||||
{
|
||||
_agentService = agentService;
|
||||
_agentTaskService = agentTaskService;
|
||||
_services = services;
|
||||
}
|
||||
|
||||
[HttpGet("/agent/task/{id}")]
|
||||
public async Task<AgentViewModel> GetAgentTask([FromRoute] string id)
|
||||
[HttpGet("/agent/{agentId}/task/{taskId}")]
|
||||
public async Task<AgentTaskViewModel?> GetAgentTask([FromRoute] string agentId, [FromRoute] string taskId)
|
||||
{
|
||||
throw new NotImplementedException("");
|
||||
var task = await _agentTaskService.GetTask(agentId, taskId);
|
||||
if (task == null) return null;
|
||||
|
||||
return AgentTaskViewModel.From(task);
|
||||
}
|
||||
|
||||
[HttpGet("/agent/tasks")]
|
||||
public async Task<PagedItems<AgentTaskViewModel>> GetAgents([FromQuery] AgentTaskFilter filter)
|
||||
{
|
||||
var taskService = _services.GetRequiredService<IAgentTaskService>();
|
||||
var tasks = await taskService.GetTasks(filter);
|
||||
var tasks = await _agentTaskService.GetTasks(filter);
|
||||
return new PagedItems<AgentTaskViewModel>
|
||||
{
|
||||
Items = tasks.Items.Select(x => AgentTaskViewModel.From(x)),
|
||||
Count = tasks.Count
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("/agent/{agentId}/task")]
|
||||
public async Task CreateAgentTask([FromRoute] string agentId, [FromBody] AgentTaskCreateModel task)
|
||||
{
|
||||
var agentTask = task.ToAgentTask();
|
||||
agentTask.AgentId = agentId;
|
||||
await _agentTaskService.CreateTask(agentTask);
|
||||
}
|
||||
|
||||
[HttpPut("/agent/{agentId}/task/{taskId}")]
|
||||
public async Task UpdateAgentTask([FromRoute] string agentId, [FromRoute] string taskId, [FromBody] AgentTaskUpdateModel task)
|
||||
{
|
||||
var agentTask = task.ToAgentTask();
|
||||
agentTask.AgentId = agentId;
|
||||
agentTask.Id = taskId;
|
||||
await _agentTaskService.UpdateTask(agentTask, AgentTaskField.All);
|
||||
}
|
||||
|
||||
[HttpPatch("/agent/{agentId}/task/{taskId}/{field}")]
|
||||
public async Task PatchAgentTaskByField([FromRoute] string agentId, [FromRoute] string taskId, [FromRoute] AgentTaskField field, [FromBody] AgentTaskUpdateModel task)
|
||||
{
|
||||
var agentTask = task.ToAgentTask();
|
||||
agentTask.AgentId = agentId;
|
||||
agentTask.Id = taskId;
|
||||
await _agentTaskService.UpdateTask(agentTask, field);
|
||||
}
|
||||
|
||||
[HttpDelete("/agent/{agentId}/task/{taskId}")]
|
||||
public async Task<bool> DeleteAgentTask([FromRoute] string agentId, [FromRoute] string taskId)
|
||||
{
|
||||
return await _agentTaskService.DeleteTask(agentId, taskId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
||||
|
||||
public class AgentTaskCreateModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string Content { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public AgentTask ToAgentTask()
|
||||
{
|
||||
return new AgentTask
|
||||
{
|
||||
Name = Name,
|
||||
Description = Description,
|
||||
Content = Content,
|
||||
Enabled = Enabled
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Tasks.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.ViewModels.Agents;
|
||||
|
||||
public class AgentTaskUpdateModel
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Content { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public AgentTask ToAgentTask()
|
||||
{
|
||||
return new AgentTask
|
||||
{
|
||||
Name = Name,
|
||||
Description = Description,
|
||||
Content = Content,
|
||||
Enabled = Enabled
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -28,8 +28,8 @@ public class AgentTaskViewModel
|
|||
Description = task.Description,
|
||||
Content = task.Content,
|
||||
Enabled = task.Enabled,
|
||||
AgentId = task.Agent.Id,
|
||||
AgentName = task.Agent.Name,
|
||||
AgentId = task.AgentId,
|
||||
AgentName = task.Agent?.Name,
|
||||
CreatedDateTime = task.CreatedDateTime,
|
||||
UpdatedDateTime = task.UpdatedDateTime
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
namespace BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
public class AgentTaskDocument : MongoBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string Content { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public string AgentId { get; set; }
|
||||
public DateTime CreatedTime { get; set; }
|
||||
public DateTime UpdatedTime { get; set; }
|
||||
}
|
||||
|
|
@ -31,6 +31,9 @@ public class MongoDbContext
|
|||
public IMongoCollection<AgentDocument> Agents
|
||||
=> Database.GetCollection<AgentDocument>($"{_collectionPrefix}_Agents");
|
||||
|
||||
public IMongoCollection<AgentTaskDocument> AgentTasks
|
||||
=> Database.GetCollection<AgentTaskDocument>($"{_collectionPrefix}_AgentTasks");
|
||||
|
||||
public IMongoCollection<ConversationDocument> Conversations
|
||||
=> Database.GetCollection<ConversationDocument>($"{_collectionPrefix}_Conversations");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Abstraction.Conversations.Models;
|
||||
using BotSharp.Abstraction.Evaluations.Settings;
|
||||
using BotSharp.Abstraction.Functions.Models;
|
||||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Routing.Models;
|
||||
using BotSharp.Abstraction.Routing.Settings;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Plugin.MongoStorage.Collections;
|
||||
using BotSharp.Plugin.MongoStorage.Models;
|
||||
|
||||
|
|
@ -261,33 +263,7 @@ public partial class MongoRepository
|
|||
var agent = _dc.Agents.AsQueryable().FirstOrDefault(x => x.Id == agentId);
|
||||
if (agent == null) return null;
|
||||
|
||||
return new Agent
|
||||
{
|
||||
Id = agent.Id,
|
||||
Name = agent.Name,
|
||||
IconUrl = agent.IconUrl,
|
||||
Description = agent.Description,
|
||||
Instruction = agent.Instruction,
|
||||
Templates = !agent.Templates.IsNullOrEmpty() ? agent.Templates
|
||||
.Select(t => AgentTemplateMongoElement.ToDomainElement(t))
|
||||
.ToList() : new List<AgentTemplate>(),
|
||||
Functions = !agent.Functions.IsNullOrEmpty() ? agent.Functions
|
||||
.Select(f => FunctionDefMongoElement.ToDomainElement(f))
|
||||
.ToList() : new List<FunctionDef>(),
|
||||
Responses = !agent.Responses.IsNullOrEmpty() ? agent.Responses
|
||||
.Select(r => AgentResponseMongoElement.ToDomainElement(r))
|
||||
.ToList() : new List<AgentResponse>(),
|
||||
Samples = agent.Samples ?? new List<string>(),
|
||||
IsPublic = agent.IsPublic,
|
||||
Disabled = agent.Disabled,
|
||||
Type = agent.Type,
|
||||
InheritAgentId = agent.InheritAgentId,
|
||||
Profiles = agent.Profiles,
|
||||
RoutingRules = !agent.RoutingRules.IsNullOrEmpty() ? agent.RoutingRules
|
||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(agent.Id, agent.Name, r))
|
||||
.ToList() : new List<RoutingRule>(),
|
||||
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agent.LlmConfig)
|
||||
};
|
||||
return TransformAgentDocument(agent);
|
||||
}
|
||||
|
||||
public List<Agent> GetAgents(AgentFilter filter)
|
||||
|
|
@ -323,33 +299,7 @@ public partial class MongoRepository
|
|||
|
||||
var agentDocs = _dc.Agents.Find(builder.And(filters)).ToList();
|
||||
|
||||
return agentDocs.Select(x => new Agent
|
||||
{
|
||||
Id = x.Id,
|
||||
Name = x.Name,
|
||||
IconUrl = x.IconUrl,
|
||||
Description = x.Description,
|
||||
Instruction = x.Instruction,
|
||||
Templates = !x.Templates.IsNullOrEmpty() ? x.Templates
|
||||
.Select(t => AgentTemplateMongoElement.ToDomainElement(t))
|
||||
.ToList() : new List<AgentTemplate>(),
|
||||
Functions = !x.Functions.IsNullOrEmpty() ? x.Functions
|
||||
.Select(f => FunctionDefMongoElement.ToDomainElement(f))
|
||||
.ToList() : new List<FunctionDef>(),
|
||||
Responses = !x.Responses.IsNullOrEmpty() ? x.Responses
|
||||
.Select(r => AgentResponseMongoElement.ToDomainElement(r))
|
||||
.ToList() : new List<AgentResponse>(),
|
||||
Samples = x.Samples ?? new List<string>(),
|
||||
IsPublic = x.IsPublic,
|
||||
Disabled = x.Disabled,
|
||||
Type = x.Type,
|
||||
InheritAgentId = x.InheritAgentId,
|
||||
Profiles = x.Profiles,
|
||||
RoutingRules = !x.RoutingRules.IsNullOrEmpty() ? x.RoutingRules
|
||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(x.Id, x.Name, r))
|
||||
.ToList() : new List<RoutingRule>(),
|
||||
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(x.LlmConfig)
|
||||
}).ToList();
|
||||
return agentDocs.Select(x => TransformAgentDocument(x)).ToList();
|
||||
}
|
||||
|
||||
public List<Agent> GetAgentsByUser(string userId)
|
||||
|
|
@ -453,4 +403,37 @@ public partial class MongoRepository
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
private Agent TransformAgentDocument(AgentDocument? agentDoc)
|
||||
{
|
||||
if (agentDoc == null) return new Agent();
|
||||
|
||||
return new Agent
|
||||
{
|
||||
Id = agentDoc.Id,
|
||||
Name = agentDoc.Name,
|
||||
IconUrl = agentDoc.IconUrl,
|
||||
Description = agentDoc.Description,
|
||||
Instruction = agentDoc.Instruction,
|
||||
Templates = !agentDoc.Templates.IsNullOrEmpty() ? agentDoc.Templates
|
||||
.Select(t => AgentTemplateMongoElement.ToDomainElement(t))
|
||||
.ToList() : new List<AgentTemplate>(),
|
||||
Functions = !agentDoc.Functions.IsNullOrEmpty() ? agentDoc.Functions
|
||||
.Select(f => FunctionDefMongoElement.ToDomainElement(f))
|
||||
.ToList() : new List<FunctionDef>(),
|
||||
Responses = !agentDoc.Responses.IsNullOrEmpty() ? agentDoc.Responses
|
||||
.Select(r => AgentResponseMongoElement.ToDomainElement(r))
|
||||
.ToList() : new List<AgentResponse>(),
|
||||
Samples = agentDoc.Samples ?? new List<string>(),
|
||||
IsPublic = agentDoc.IsPublic,
|
||||
Disabled = agentDoc.Disabled,
|
||||
Type = agentDoc.Type,
|
||||
InheritAgentId = agentDoc.InheritAgentId,
|
||||
Profiles = agentDoc.Profiles,
|
||||
RoutingRules = !agentDoc.RoutingRules.IsNullOrEmpty() ? agentDoc.RoutingRules
|
||||
.Select(r => RoutingRuleMongoElement.ToDomainElement(agentDoc.Id, agentDoc.Name, r))
|
||||
.ToList() : new List<RoutingRule>(),
|
||||
LlmConfig = AgentLlmConfigMongoElement.ToDomainElement(agentDoc.LlmConfig)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
using BotSharp.Abstraction.Repositories.Filters;
|
||||
using BotSharp.Abstraction.Tasks.Models;
|
||||
using BotSharp.Plugin.MongoStorage.Collections;
|
||||
|
||||
namespace BotSharp.Plugin.MongoStorage.Repository;
|
||||
|
||||
public partial class MongoRepository
|
||||
{
|
||||
#region Task
|
||||
public PagedItems<AgentTask> GetAgentTasks(AgentTaskFilter filter)
|
||||
{
|
||||
var pager = filter.Pager ?? new Pagination();
|
||||
var builder = Builders<AgentTaskDocument>.Filter;
|
||||
var filters = new List<FilterDefinition<AgentTaskDocument>>() { builder.Empty };
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.AgentId))
|
||||
{
|
||||
filters.Add(builder.Eq(x => x.AgentId, filter.AgentId));
|
||||
}
|
||||
|
||||
if (filter.Enabled.HasValue)
|
||||
{
|
||||
filters.Add(builder.Eq(x => x.Enabled, filter.Enabled.Value));
|
||||
}
|
||||
|
||||
var filterDef = builder.And(filters);
|
||||
var sortDef = Builders<AgentTaskDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var totalTasks = _dc.AgentTasks.CountDocuments(filterDef);
|
||||
var taskDocs = _dc.AgentTasks.Find(filterDef).Sort(sortDef).Skip(pager.Offset).Limit(pager.Size).ToList();
|
||||
|
||||
var agentIds = taskDocs.Select(x => x.AgentId).Distinct().ToList();
|
||||
var agents = GetAgents(new AgentFilter { AgentIds = agentIds });
|
||||
|
||||
var tasks = taskDocs.Select(x => new AgentTask
|
||||
{
|
||||
Id = x.Id,
|
||||
Name = x.Name,
|
||||
Description = x.Description,
|
||||
Enabled = x.Enabled,
|
||||
AgentId = x.AgentId,
|
||||
Content = x.Content,
|
||||
CreatedDateTime = x.CreatedTime,
|
||||
UpdatedDateTime = x.UpdatedTime,
|
||||
Agent = agents.FirstOrDefault(a => a.Id == x.AgentId)
|
||||
}).ToList();
|
||||
|
||||
return new PagedItems<AgentTask>
|
||||
{
|
||||
Items = tasks,
|
||||
Count = (int)totalTasks
|
||||
};
|
||||
}
|
||||
|
||||
public AgentTask? GetAgentTask(string agentId, string taskId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(taskId)) return null;
|
||||
|
||||
var taskDoc = _dc.AgentTasks.AsQueryable().FirstOrDefault(x => x.Id == taskId);
|
||||
if (taskDoc == null) return null;
|
||||
|
||||
var agentDoc = _dc.Agents.AsQueryable().FirstOrDefault(x => x.Id == taskDoc.AgentId);
|
||||
var agent = TransformAgentDocument(agentDoc);
|
||||
|
||||
var task = new AgentTask
|
||||
{
|
||||
Id = taskDoc.Id,
|
||||
Name = taskDoc.Name,
|
||||
Description = taskDoc.Description,
|
||||
Enabled = taskDoc.Enabled,
|
||||
AgentId = taskDoc.AgentId,
|
||||
Content = taskDoc.Content,
|
||||
CreatedDateTime = taskDoc.CreatedTime,
|
||||
UpdatedDateTime = taskDoc.UpdatedTime,
|
||||
Agent = agent
|
||||
};
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
public void InsertAgentTask(AgentTask task)
|
||||
{
|
||||
var taskDoc = new AgentTaskDocument
|
||||
{
|
||||
Id = Guid.NewGuid().ToString(),
|
||||
Name = task.Name,
|
||||
Description = task.Description,
|
||||
Enabled = task.Enabled,
|
||||
AgentId = task.AgentId,
|
||||
Content = task.Content,
|
||||
CreatedTime = DateTime.UtcNow,
|
||||
UpdatedTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_dc.AgentTasks.InsertOne(taskDoc);
|
||||
}
|
||||
|
||||
public void UpdateAgentTask(AgentTask task, AgentTaskField field)
|
||||
{
|
||||
if (task == null || string.IsNullOrEmpty(task.Id)) return;
|
||||
|
||||
var filter = Builders<AgentTaskDocument>.Filter.Eq(x => x.Id, task.Id);
|
||||
var taskDoc = _dc.AgentTasks.Find(filter).FirstOrDefault();
|
||||
if (taskDoc == null) return;
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case AgentTaskField.Name:
|
||||
taskDoc.Name = task.Name;
|
||||
break;
|
||||
case AgentTaskField.Description:
|
||||
taskDoc.Description = task.Description;
|
||||
break;
|
||||
case AgentTaskField.Enabled:
|
||||
taskDoc.Enabled = task.Enabled;
|
||||
break;
|
||||
case AgentTaskField.Content:
|
||||
taskDoc.Content = task.Content;
|
||||
break;
|
||||
case AgentTaskField.All:
|
||||
taskDoc.Name = task.Name;
|
||||
taskDoc.Description = task.Description;
|
||||
taskDoc.Enabled = task.Enabled;
|
||||
taskDoc.Content = task.Content;
|
||||
break;
|
||||
}
|
||||
|
||||
taskDoc.UpdatedTime = DateTime.UtcNow;
|
||||
_dc.AgentTasks.ReplaceOne(filter, taskDoc);
|
||||
}
|
||||
|
||||
public bool DeleteAgentTask(string agentId, string taskId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(taskId)) return false;
|
||||
|
||||
var filter = Builders<AgentTaskDocument>.Filter.Eq(x => x.Id, taskId);
|
||||
var taskDeleted = _dc.AgentTasks.DeleteOne(filter);
|
||||
return taskDeleted.DeletedCount > 0;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -217,9 +217,9 @@ public partial class MongoRepository
|
|||
if (!string.IsNullOrEmpty(filter.UserId)) filters.Add(builder.Eq(x => x.UserId, filter.UserId));
|
||||
|
||||
var filterDef = builder.And(filters);
|
||||
var sortDefinition = Builders<ConversationDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var sortDef = Builders<ConversationDocument>.Sort.Descending(x => x.CreatedTime);
|
||||
var pager = filter?.Pager ?? new Pagination();
|
||||
var conversationDocs = _dc.Conversations.Find(filterDef).Sort(sortDefinition).Skip(pager.Offset).Limit(pager.Size).ToList();
|
||||
var conversationDocs = _dc.Conversations.Find(filterDef).Sort(sortDef).Skip(pager.Offset).Limit(pager.Size).ToList();
|
||||
var count = _dc.Conversations.CountDocuments(filterDef);
|
||||
|
||||
foreach (var conv in conversationDocs)
|
||||
|
|
|
|||
Loading…
Reference in a new issue